0

I have a query that displays the total value (sum of amount) for each day. The query:

SELECT CAST(date AS DATE), SUM(amount) AS total_amount FROM table
WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
GROUP BY CAST(date AS DATE)

The CAST is to abbreviate the datetime format to just a date.

Now I want to select only the day which has the highest sum with the max function. To do this I tried writing the following aggregate query:

SELECT s.date, s.total_amount
FROM (SELECT CAST(date AS DATE), SUM(amount) AS total_amount FROM table
WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
GROUP BY CAST(date AS DATE)) s
WHERE s.total_amount = (SELECT MAX(s.total_amount) FROM table)

This does not work. I know the problem is with the final WHERE clause, but I need help with making it work.

4
  • 1
    please tag your SQL engine. Commented May 12, 2020 at 8:36
  • 1
    Tag the DBMS that you are using. Commented May 12, 2020 at 8:40
  • I'm not using a specific SQL engine/DBMS so I need a general (universal) SQL query. Commented May 12, 2020 at 8:43
  • 2
    @ire: the "universal" SQL is the either the one row_number() (see zealous' answer) or the CTE from Yogesh's answer Commented May 12, 2020 at 9:29

3 Answers 3

2

Use ORDER BY with LIMIT :

SELECT CAST(date AS DATE), SUM(amount) AS total_amount 
FROM table
WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
GROUP BY CAST(date AS DATE)
ORDER BY total_amount DESC
LIMIT 1;

If you are working with SQL Server then you can use TOP :

SELECT TOP (1) CAST(date AS DATE), SUM(amount) AS total_amount 
FROM table
WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
GROUP BY CAST(date AS DATE)
ORDER BY total_amount DESC;

If you want ties then you can use window function :

SELECT t.*
FROM (SELECT CAST(date AS DATE), SUM(amount) AS total_amount,
             RANK() OVER (ORDER BY SUM(amount) DESC) as Seq
      FROM table
      WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
      GROUP BY CAST(date AS DATE)
     ) t
WHERE seq = 1;

You can use CTE :

WITH CTE AS (
     SELECT CAST(date AS DATE), SUM(amount) AS total_amount 
     FROM table
     WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
     GROUP BY CAST(date AS DATE)
)  
SELECT c.*
FROM CTE C
WHERE C.total_amount = (SELECT MAX(total_amount) FROM CTE);

Note : If your DBMS doesn't support CTE expression then you need repeat the SELECT statement in Subquery.

SELECT CAST(date AS DATE), SUM(amount) AS total_amount 
FROM table
WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
GROUP BY CAST(date AS DATE)
HAVING SUM(amount) = (SELECT MAX(total_amount)
                      FROM (SELECT CAST(date AS DATE), SUM(amount) AS total_amount 
                            FROM table
                            WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
                            GROUP BY CAST(date AS DATE)
                           ) t
                     );
Sign up to request clarification or add additional context in comments.

2 Comments

This works but I'd like to know how to do it with an aggregate function. Do you know how I could make it work?
@ire: you can't have an aggregate without using aggregate function. That doesn't make sense.
0

If you are using SQL Server then you can use TOP

SELECT TOP 1 CAST(date AS DATE), SUM(amount) AS total_amount 
FROM table
WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
GROUP BY CAST(date AS DATE)
ORDER BY total_amount DESC

Use window function row_number() - should work with MySQL 8.0, PostgreSQL, Oracle and SQL Server.

select
    date,
    total_amount
from
(
    SELECT 
        CAST(date AS DATE) as date, 
        SUM(amount) AS total_amount,
        row_number() over (order by SUM(amount) desc) as rnk 
    FROM table
    WHERE date BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
    GROUP BY CAST(date AS DATE)
) val
where rnk = 1

1 Comment

I'm trying to avoid using the top or rnk and use an aggregate function like I showed in my post. Do you know how I could make it work?
0

SELECT s.dt, s.total_amount FROM (SELECT CAST(date AS DATE) as dt, SUM(amount) AS total_amount FROM table WHERE CAST(date as date) BETWEEN '2019-01-01' AND '2019-12-31' GROUP BY CAST(date AS DATE)) s WHERE s.total_amount = (Select max(total_amount) FROM (SELECT CAST(date AS DATE) as dt, SUM(amount) AS total_amount FROM table WHERE CAST(date as date) BETWEEN '2019-01-01' AND '2019-12-31' GROUP BY CAST(date AS DATE)) ss )

1 Comment

I think the above will give you what you want but I am still trying to ascertain why you can not use rank or top functions for your need.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.