I’m working with the database and servlets, there was such a problem. I need to receive data from the database of 6 pieces per page, for this I made such a request
SELECT *, COUNT(*) AS 'count'
FROM product
INNER JOIN product_category
on product.product_category_id = product_category.id
INNER JOIN company_manufacturer_product
on product.company_manufacturer_product_id =
company_manufacturer_product.id
GROUP BY 1 LIMIT 6 OFFSET 0;
where 6 is the maximum number of items per page and 0 is the page number multiplied by the maximum quantity of goods. But with such an implementation on the second page I have duplicate products how can i improve it?
The part of the code where I form the request:
StringBuilder startResponse = new StringBuilder("SELECT *, COUNT(*) AS 'count' FROM product " +
"INNER JOIN product_category on product.product_category_id = product_category.id " +
"INNER JOIN company_manufacturer_product on product.company_manufacturer_product_id=company_manufacturer_product.id");
if (nonNull(form.getProductMax()) && nonNull(form.getPage())) {
startResponse.append(" LIMIT ").append(form.getProductMax()).append(" OFFSET ").append(form.getPage() * form.getProductMax());
}
My database respone without LIMIT and OFFSET:
My database respone when I use the query that described above, this request is sent to the database when I turn to the first page with the goods:
When I turn to the second page with goods, I send such a request to the database
SELECT * , COUNT(*) AS 'count'
FROM product
INNER JOIN product_category
on product.product_category_id = product_category.id
INNER JOIN company_manufacturer_product
on product.company_manufacturer_product_id =
company_manufacturer_product.id
GROUP BY 1 LIMIT 6 OFFSET 6;
and i have response like that:
I can not understand what the problem is. I have to use requests through COUNT! How prove it?
Not against the solution of this question, according to the above method, adding order by to original sql can solve the problem.
But I think I have a better practice for pagination: using parameters like has_more, last_product_id and limit_num to connect clients with server.
has_more indicates more data in server whether or not left;
last_product_id indicates the id of last response data;
limit_num indicates the number of per page.
So, client can using has_more to determine sending a request or not, if it is, client sends a request with last_product_id and limit_num to server; and for server, the sql can be this:
select * from table where id < $last_product_id order by id desc
limit $limit_num + 1; =>$datas
And, count($datas) and $limit_num to calculate the value of has_more and last_product_id:
$has_more = 0;
$data_num = count($datas);
if ($data_num > $page_limit) {
$has_more = 1;
array_pop($datas);
$data_num--;
}
$last_product_id = end($datas)['id'] ?? 0;
SELECT *, COUNT(product.id) AS 'count' FROM product INNER JOIN
product_category on product.product_category_id = product_category.id
INNER JOIN company_manufacturer_product on
product.company_manufacturer_product_id=company_manufacturer_product.id
group by product.id order by product.id LIMIT 6 OFFSET 0;
Related
I am trying to implement sqlparser and using gsqlparser from here. The source of the jar is in Java but I am implementing the same in Scala.
Below is my query which contains a join condition.
SELECT e.last_name AS name, e.commission_pct comm, e.salary * 12 "Annual Salary" FROM scott.employees AS e right join scott.companies as c on c.orgid = e.orgid and c.orgname = e.orgn WHERE e.salary > 1000 ORDER BY e.first_name, e.last_name
I was able to parse the query to read names & aliases of columns, where conditions, table names (checking the table names directly inside the query) as below.
val sqlParser = new TGSqlParser(EDbVendor.dbvsnowflake)
sqlParser.sqltext = "SELECT e.last_name AS name, e.commission_pct comm, e.salary * 12 \"Annual Salary\" FROM scott.employees AS e right join scott.companies as c on c.orgid = e.orgid and c.orgname = e.orgn WHERE e.salary > 1000 ORDER BY e.first_name, e.last_name"
val selectStmnt = sqlParser.sqltext
println("Columns List:")
for(i <- 0 until selectStmnt.getResultColumnList.size()) {
val resCol = selectStmnt.getResultColumnList.getResultColumn(i)
println("Column: " + resCol.getExpr.toString + " Alias: " + resCol
.getAliasClause().toString)
}
Output:
Columns List:
Column: e.last_name Alias: name
Column: e.commission_pct Alias: comm
Column: e.salary * 12 Alias: "Annual Salary"
I am trying to parse the join condition and get the details inside it
for(j <- 0 until selectStmnt.getJoins.size()) {
println(selectStmnt.getJoins.getJoin(j).getTable)
}
The problem here is there is only one join condition in the query, so the size returned is 1.
Hence the output is scott.employees.
If I do it a bit different as below using getJoinItems
println("Parsing Join items")
for(j <- 0 until selectStmnt.getJoins.size()) {
println(selectStmnt.getJoins.getJoin(j).getJoinItems)
}
I get the output by cutting off the first table from the join condition as below:
scott.companies as c on c.orgid = e.orgid and c.orgname = e.orgn
The method: getJoinItems() returns a list: TJoinItemList which I thought of traversing through. But even its size is 1.
println(selectStmnt.getJoins.getJoin(j).getJoinItems.size()) -> 1
I am out of ideas now. Could anyone let me know how can I parse the query's join condition and get the table names inside the join ?
I don't have access to Snowflake dialect in GSP but I mimicked this scenario with Teradata dialect using the following query and created a sql parser.
SELECT e.last_name as name
FROM department d
RIGHT JOIN
trimmed_employee e
ON d.dept_id = e.emp_id
WHERE e.salary > 1000
ORDER BY e.first_name
Here is the Groovy code of getting both the tables department, trimmed_employee. It boils down to iterating over each join and while doing so collect the current join's items (joinItems) using curJoin.joinItems only if it is not null.
stmt.joins.asList().collect { curJoin ->
[curJoin.table] + (curJoin?.joinItems?.asList()?.collect { joinItems -> joinItems.table } ?: [])
}.flatten()
Result:
department
trimmed_employee
For this simple sql that you mentioned in my case, the following code also works.
stmt.tables.asList()
Users
Userid
userName
password
status
Issue
IssueNum
issueDescription
status
creationdate
IssueAssigned
issueNumber
issueAssignedTo
issueAssignedBy
comments
In my primefaces datatable I am fetching these value using following query
SELECT I.issue_number, I.issue_describtion, U.first_name,US.first_name
FROM ISSUES I
LEFT JOIN ISSUE_ASSIGNED IA
ON I.issue_number = IA.Issue_number
LEFT JOIN USERS U
ON U.id = IA.assigned_to_user_id
LEFT JOIN USERS US
ON US.id = IA.assigned_by_user_id
The Admin who is also a user assigns issue to another user
In MSSQL this above query works fine gives me proper record for U.firstName and US.FirstName as they are different user.
query in MSSQL returns
PER-1675 Perform - Evaluation Form Export does not pull any data in Legacy Export Tool (Due 8/14) Ameh Sandip
PER-2048 Calculation of scores fails when the lower/upper bound value of a calculation text result is a Ameh Sandip
But in Hibernate for the same query both firstName and US.firstName gives same result
code
#Override
public List<Object> getIssueListForAssigingIssue (){
List<Object> allIssueList = getHibernateTemplate()
.getSessionFactory()
.getCurrentSession().createSQLQuery("SELECT I.issue_number, I.issue_describtion, IT.issue_type,U.first_name ,US.first_name "
+ "FROM ISSUES I "
+ "LEFT JOIN ISSUE_ASSIGNED IA "
+ "ON I.issue_number = IA.Issue_number "
+ "LEFT JOIN USERS U "
+ "ON U.id = IA.assigned_to_user_id "
+ "LEFT JOIN USERS US "
+ "ON US.id = IA.assigned_by_user_id ").list();
return allIssueList;
}
query in hibernate returns
PER-1675 Perform - Evaluation Form Export does not pull any data in Legacy Export Tool (Due 8/14) Ameh Ameh
PER-2048 Calculation of scores fails when the lower/upper bound value of a calculation text result is a Ameh Ameh
I was able to solve it by giving alias to both the column somehow hibernate gets confused between the two columns
I am trying to use the below query with Hibernate's session.createSQLQuery.
The Entity object corresponding to user has an attribute called address.
The address object is created out of 5 fields from table 'user'.
If I do not use an SQLQuery it gets filled auto-magically.
However without the SQLQuery I can't get all the info I would get from the desired joins shown below.
The user entity object also attributes like accessPlan which I am filling up using
.addEntity("accessPlan", AccessPlan.class)
Query:
SELECT
user.*,
ap.*,
country.*,
auth.*,
GROUP_CONCAT(coup.code SEPARATOR ' ') coupons
FROM
user
INNER JOIN access_plan ap ON (user.access_plan = ap.id)
INNER JOIN country ON (user.country=country.code)
LEFT JOIN user_auth auth ON (user.id = auth.userid)
LEFT JOIN (
SELECT
trans.user_id,coupon.code
FROM
payments_transaction AS trans
INNER JOIN payments_coupon coupon ON (trans.payments_coupon_id=coupon.id)
) coup ON (user.id=coup.user_id)
GROUP BY user.id;
What can be the easiest way to fill up the composed address object while using the SQLQuery?
OR
Is there a way to avoid using SQLQuery for a query like this?
Please check below example from the section 'Returning multiple entities'
String sql = "SELECT ID as {c.id}, NAME as {c.name}, " +
"BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
"FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";
List loggedCats = sess.createSQLQuery(sql)
.addEntity("cat", Cat.class)
.addEntity("mother", Cat.class).list()
In your case, cat = user, mother = address... somewhat like that.
I do not have anything to try out at the moment but I guess this will help.
Our Java Application is running very slowly.
This is the case for various reasons, one of the main maybe being that the MySQL code within the application uses two different tables to get this data, doing joins. Is anyone able to advise how this Query could be written better for performance?
SELECT DISTINCT uniqueId
FROM advertisementmodule
JOIN advertisement ON advertisementmodule.idAdvertisement = advertisement.idAdvertisement
JOIN advertisementschedule ON advertisement.idAdvertisementSchedule = advertisementschedule.idAdvertisementSchedule
JOIN adschedulegroup ON advertisementschedule.idAdScheduleGroup = adschedulegroup.idAdScheduleGroup
WHERE adschedulegroup.publisherCode = 'ABC';
SELECT *
FROM taurustour
JOIN searchthemestaurus
WHERE uniqueId IN (
'18538'
,'17142'
,'11248'
,'18458'
)
AND air IS true;
Which table isuniqueId in?
A little more readable:
SELECT DISTINCT uniqueId
FROM advertisementmodule AS m
JOIN advertisement AS a
ON m.idAdvertisement = a.idAdvertisement
JOIN advertisementschedule AS s
ON a.idAdvertisementSchedule = s.idAdvertisementSchedule
JOIN adschedulegroup AS g
ON s.idAdScheduleGroup = g.idAdScheduleGroup
WHERE g.publisherCode = 'ABC';
Do you have an index starting with publisherCode ?
I try to make a namedQuery:
#NamedQuery(name = "Interval.findByMemoryType",
query = "select i from Interval i JOIN i.intervalDatas id "
+ "where id.fragments.memoryType = :memoryType")
My problem is, that fragments is a list of fragment. I'm only interested in memory type of first element in the list.
So I should have something like this:
#NamedQuery(name = "Interval.findByMemoryType",
query = "select i from Interval i JOIN i.intervalDatas id "
+ "(select first(id.fragments)) as fid) where fid.memoryType = :memoryType")
But I get always “The query contains a malformed ending” problem.
Could somebody help me??
You can take the first result:
TypedQuery<Interval> q = em.createQuery ("Interval.findByMemoryType", Interval.class);
q.setParameter("memoryType", memoryType);//+other parameters if you have
Interval interval = q.getSingleResult();
The small disadvantage is that it may load all its intervalDatas (depending on the mapping). Also check the documentation for possible exceptions.