简体   繁体   中英

SQL- Use CASE without GROUP BY

How to get the sum of the value without GROUP BY using CASE expression in SQL (or please suggest any other best way to achieve this)

Query :

SELECT 
    CASE
        WHEN [lab_date] <= '2018-03-24'
             AND [lab_date] >= '2018-01-01'
        THEN(ISNULL(SUM(ISNULL([cost], 0) * 5 / 100), 0))
        WHEN [lab_date] >= '2018-03-25'
        THEN(ISNULL((SUM(ISNULL([cost], 0))) - (SUM(ISNULL([cost], 0) * 5 / 100)), 0))
    END AS [tax]
FROM [LABOR];

+-------------+--------+
|  lab_date   |  cost  |
+-------------+--------+
| 2018-03-12  |  75.00 |
| 2018-03-01  | 150.00 |
| 2018-03-11  | 450.00 |
| 2018-03-13  |  37.50 |
| 2018-03-15  | 150.00 |
+-------------+--------+

Getting this with GROUP by lab_date

+-------+
|  tax  |
+-------+
| 15.00 |
| 22.50 |
|  3.75 |
|  1.88 |
+-------+

How we can get the result like below

+-------+
|  tax  |
+-------+
| 43.13 |
+-------+

I think you want conditional aggregation . . . where the case is the argument to SUM() :

SELECT SUM(CASE WHEN lab_date <= '2018-03-24' AND lab_date >= '2018-01-01' THEN cost * 5.0/100
                WHEN lab_date >= '2018-03-25' THEN cost - cost * 5.0/100
                ELSE 0
           END)  as tax         
FROM LABOR ;

Note that SQL Server does integer division. So I don't recommend ever writing 5/100, because that will evaluate to 0 . Even if the multiplication is performed first, not including the decimal point is a bad habit.

Why circumvent the very feature that is exactly designed for your purpose?

Try something like this:

with
taxes_before(lab_date, tax) as (
  select lab_date, cost*0.05
  from labor
  where lab_date between '2018-01-01' and '2018-03-24'
),
taxes_after(lab_date, tax) as (
  select lab_date, cost*0.95
  from labor
  where lab_date >= '2018-01-25'
),
taxes_all(lab_date, tax) as (
  select lab_date, tax from taxes_before
  union select lab_date, tax from taxes_after
)
select sum(tax)
from taxes_all

Disclaimer: I don't have a MS SQL Server here, so shame on me if there is a syntax error.

Explanation: You compute the two sets for the time before day X and the time after day X separately. Then you union those two sets and just group as usual.

Why is this better than the case expression? The WHERE clause benefits from a (possible) index on your date column, but the case statement is evaluated for each row and hence your query scans over every row in your table.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM