如何在GROUP BY
中使用CASE
表达式获取不使用SQL
的值的总和
(或者请建议任何其他最好的方法来实现这一点)
查询:
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 |
+-------------+--------+
通过lab_date
获取此组+-------+
| tax |
+-------+
| 15.00 |
| 22.50 |
| 3.75 |
| 1.88 |
+-------+
我们如何获得如下结果
+-------+
| tax |
+-------+
| 43.13 |
+-------+
答案 0 :(得分:4)
我认为你想要条件聚合。 。 。其中case
是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 ;
请注意,SQL Server执行整数除法。所以我建议不要写5/100,因为这会评估为0
。即使首先执行乘法,不包括小数点也是一个坏习惯。
答案 1 :(得分:0)
为什么要绕过为您的目的而精心设计的功能?
尝试这样的事情:
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
免责声明:我这里没有MS SQL Server,如果语法错误,我会感到羞耻。
说明:分别计算X天之前的时间和X之后的时间的两个集合。然后你将这两组联合起来并像往常一样分组。
为什么这比案例表达更好? WHERE子句受益于日期列上的(可能)索引,但是对每行评估case语句,因此查询将扫描表中每个行。