Usage of GROUP BY and MIN with HSQLDB

妖精的绣舞 提交于 2020-01-16 11:58:12

问题



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??


回答1:


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



回答2:


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).




回答3:


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


来源:https://stackoverflow.com/questions/16733284/usage-of-group-by-and-min-with-hsqldb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!