I need to execute a query for retrieving the item with the soonest expire date for each customer.
I have the following product table:
PRODUCT
|ID|NAME |EXPIRE_DATE|CUSTOMER_ID
1 |p1 |2013-12-31 |1
2 |p2 |2014-12-31 |1
3 |p3 |2013-11-30 |2
and I would like to obtain the following result:
|ID|EXPIRE_DATE|CUSTOMER_ID
1 |2013-12-31 |1
3 |2013-11-30 |2
With Mysql I would have a query like:
SELECT ID,min(EXPIRE_DATE),CUSTOMER_ID
FROM PRODUCT
GROUP BY CUSTOMER_ID
But I am using HyperSQL and I am not able to obtain this result.
With HSQLDB I get this error: java.sql.SQLSyntaxErrorException: expression not in aggregate or GROUP BY columns: PRODUCT.ID
.
If in HyperSQL I modify the last row of the query like GROUP BY CUSTOMER_ID,ID
I obtain the same entries of the original table.
How can I compute the product with the soonest expire date for each customer with HSQLDB??
MySQL allows non ANSI group by which can often give wrong results. HSQL is acting correctly.
There are 2 options:
Remove ID
SELECT min(EXPIRE_DATE),CUSTOMER_ID
FROM PRODUCT
GROUP BY CUSTOMER_ID
Or, assuming that ID increases with EXPIRE_DATE
SELECT MIN(ID),min(EXPIRE_DATE),CUSTOMER_ID
FROM PRODUCT
GROUP BY CUSTOMER_ID
If you do need ID however, then you have to JOIN back
SELECT
P.ID, P.EXPIRE_DATE, P.CUSTOMER_ID
FROM
(
SELECT min(EXPIRE_DATE) AS minEXPIRE_DATE,CUSTOMER_ID
FROM PRODUCT
GROUP BY CUSTOMER_ID
) X
JOIN
PRODUCT P ON X.minEXPIRE_DATE = P.EXPIRE_DATE AND X.CUSTOMER_ID = P.CUSTOMER_ID
However, I think HSQL supports the ANY aggregate. This gives an arbitrary ID per MIN/GROUP BY.
SELECT ANY(ID),min(EXPIRE_DATE),CUSTOMER_ID
FROM PRODUCT
GROUP BY CUSTOMER_ID
In MySQL, you are getting an arbitrary id
for each customer. In most other dialects of SQL, you need to specify which you want. This will work:
SELECT min(ID), min(EXPIRE_DATE), CUSTOMER_ID
FROM PRODUCT
GROUP BY CUSTOMER_ID;
If you are trying to get the id
associated with the smallest expire date, then MySQL is not doing that. Here is one way to do this:
select p.*
from Product p join
(select customer_id, min(Expire_date) as min_ed
from Product p
group by customer_id
) psum
on p.customer_id = psum.customer_id and p.Expire_date = psum.min_ed
This is standard SQL and will run on any database (although some databases have functionality that is cleaner and more efficient).
Assuming sub queries are supported, you can join the table on itself like such:
SELECT P.ID, P.EXPIRE_DATE, P.CUSTOMER_ID
FROM PRODUCT P
JOIN (
SELECT CUSTOMER_ID, MIN(EXPIRE_DATE) MIN_EXPIRE_DATE
FROM PRODUCT
GROUP BY CUSTOMER_ID
) P2 ON P.CUSTOMER_ID = P2.CUSTOMER_ID
AND P.EXPIRE_DATE = P2.MIN_EXPIRE_DATE
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.