使用以下结果集:
| DATE | BUSINESS | COLLEAGUE | POSITION | HOURS | STANDARDHOURS | COUNTER | OVER16 | OVER32 | OVER48 | ----------------------------------------------------------------------------------------------------------------- | 2013-01-01 | a | bob jones | analyst | 168 | 168 | 1 | 0 | 0 | 0 | | 2013-01-01 | a | cindy jones | assistant | 184 | 168 | 1 | 1 | 0 | 0 | | 2013-01-01 | b | tim harris | programmer | 200 | 168 | 1 | 1 | 1 | 0 | | 2013-01-01 | b | tom white | manager | 216 | 168 | 1 | 1 | 1 | 1 | | 2013-02-01 | a | bob jones | analyst | 176 | 176 | 1 | 0 | 0 | 0 | | 2013-02-01 | a | cindy jones | assistant | 176 | 176 | 1 | 0 | 0 | 0 | | 2013-02-01 | b | tim harris | programmer | 200 | 176 | 1 | 1 | 0 | 0 | | 2013-02-01 | b | tom white | manager | 216 | 176 | 1 | 1 | 1 | 0 |
使用此查询:
SELECT c.date,
c.business,
CASE
WHEN Sum(c.over16) > 0 THEN ( Sum(c.over16) / Sum(c.counter) ) * 100
ELSE 0
END AS percOver16,
CASE
WHEN Sum(c.over32) > 0 THEN ( Sum(c.over32) / Sum(c.counter) ) * 100
ELSE 0
END AS percOver32,
CASE
WHEN Sum(c.over48) > 0 THEN ( Sum(c.over48) / Sum(c.counter) ) * 100
ELSE 0
END AS percOver48
FROM (SELECT a.date,
a.business,
a.colleague,
a.position,
a.hours,
b.standardhours,
1 AS counter,
CASE
WHEN a.hours >= b.standardhours + 16 THEN 1
ELSE 0
END AS over16,
CASE
WHEN a.hours >= b.standardhours + 32 THEN 1
ELSE 0
END AS over32,
CASE
WHEN a.hours >= b.standardhours + 48 THEN 1
ELSE 0
END AS over48
FROM colleaguetime a
JOIN businesshours b
ON b.date = a.date) c
GROUP BY c.date,
c.business
我明白了:
| DATE | BUSINESS | PERCOVER16 | PERCOVER32 | PERCOVER48 | ---------------------------------------------------------------- | 2013-01-01 | a | 0 | 0 | 0 | | 2013-01-01 | b | 100 | 100 | 0 | | 2013-02-01 | a | 0 | 0 | 0 | | 2013-02-01 | b | 100 | 0 | 0 |
期望的结果是:
| DATE | BUSINESS | PERCOVER16 | PERCOVER32 | PERCOVER48 | ---------------------------------------------------------------- | 2013-01-01 | a | 50 | 0 | 0 | | 2013-01-01 | b | 100 | 100 | 50 | | 2013-02-01 | a | 0 | 0 | 0 | | 2013-02-01 | b | 100 | 50 | 0 |
使用CTE有更简单的方法吗?
答案 0 :(得分:7)
我相信你遇到的问题是整数除法问题。您希望在进行除法之前将值转换为十进制或浮点格式。这是一种方法:
SELECT c.date,
c.business,
CASE
WHEN Sum(c.over16) > 0 THEN ( Sum(c.over16*1.0) / Sum(c.counter) ) * 100
ELSE 0
END AS percOver16,
CASE
WHEN Sum(c.over32) > 0 THEN ( Sum(c.over32*1.0) / Sum(c.counter) ) * 100
ELSE 0
END AS percOver32,
CASE
WHEN Sum(c.over48) > 0 THEN ( Sum(c.over48*1.0) / Sum(c.counter) ) * 100
ELSE 0
END AS percOver48
编辑:
最简单的替代方法是在子查询中更改计数器的定义:
1.0 as counter, -- This has a decimal point so it can be used for division
这会将其定义为非整数的数字数据类型。
作为生产代码的一般规则,我希望在发生分割时进行这些转换,以防止意外错误。在某个地方,你或其他人可以看到像1.0 as counter
这样的行,并认为“那是愚蠢的。Counter
应该是一个整数。”然后你或他或她改变它,然后东西就会破裂。或者有人看到sum(c.counter)
并认为“那是愚蠢的。它只能count(*)
或count(c.counter)
。
另一方面,对于特殊代码,我可能只是制作计数器1.0
。
答案 1 :(得分:6)
您可以通过在子查询中使用以下内容来解决此问题:
SELECT a.date, a.business, a.colleague, a.position, a.hours, b.standardHours,
1 AS counter,
CASE WHEN a.hours >= b.standardHours + 16
THEN 1.0 ELSE 0.0 END AS over16,
CASE WHEN a.hours >= b.standardHours + 32
THEN 1.0 ELSE 0.0 END AS over32,
CASE WHEN a.hours >= b.standardHours + 48
THEN 1.0 ELSE 0.0 END AS over48
FROM colleagueTime a
JOIN businessHours b ON b.date = a.date;
请参阅Demo
不是使用1
和0
,而是将值更改为1.0
,因此它们是小数而不是整数。
或者正如戈登指出的那样,你可以使用1.0作为计数器值:
SELECT a.date, a.business, a.colleague, a.position, a.hours, b.standardHours,
1.0 AS counter,
CASE WHEN a.hours >= b.standardHours + 16
THEN 1 ELSE 0 END AS over16,
CASE WHEN a.hours >= b.standardHours + 32
THEN 1 ELSE 0 END AS over32,
CASE WHEN a.hours >= b.standardHours + 48
THEN 1 ELSE 0 END AS over48
FROM colleagueTime a
JOIN businessHours b ON b.date = a.date;
答案 2 :(得分:5)
更改
Sum(c.over16) / Sum(c.counter)
为:
cast(SUM(c.over16) as float) / cast(SUM(c.counter) as float)
(以及所有其他的。)
划分整数会产生整数。你需要先施放浮动。