1

使用以下结果集:

| 日期 | 业务 | 同事 | 职位 | 小时 | 标准时间 | 柜台 | 16岁以上 | 超过32 | 48岁以上 |
-------------------------------------------------- -------------------------------------------------- -------------
| 2013-01-01 | 一个 | 鲍勃琼斯 | 分析师 | 168 | 168 | 1 | 0 | 0 | 0 |
| 2013-01-01 | 一个 | 辛迪琼斯 | 助理 | 184 | 168 | 1 | 1 | 0 | 0 |
| 2013-01-01 | 乙 | 蒂姆哈里斯 | 程序员 | 200 | 168 | 1 | 1 | 1 | 0 |
| 2013-01-01 | 乙 | 汤姆·怀特 | 经理 | 216 | 168 | 1 | 1 | 1 | 1 |
| 2013-02-01 | 一个 | 鲍勃琼斯 | 分析师 | 176 | 176 | 1 | 0 | 0 | 0 |
| 2013-02-01 | 一个 | 辛迪琼斯 | 助理 | 176 | 176 | 1 | 0 | 0 | 0 |
| 2013-02-01 | 乙 | 蒂姆哈里斯 | 程序员 | 200 | 176 | 1 | 1 | 0 | 0 |
| 2013-02-01 | 乙 | 汤姆·怀特 | 经理 | 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 

我得到:

| 日期 | 业务 | PERCOVER16 | PERCOVER32 | PERCOVER48 |
-------------------------------------------------- --------------
| 2013-01-01 | 一个 | 0 | 0 | 0 |
| 2013-01-01 | 乙 | 100 | 100 | 0 |
| 2013-02-01 | 一个 | 0 | 0 | 0 |
| 2013-02-01 | 乙 | 100 | 0 | 0 |

期望的结果是:

| 日期 | 业务 | PERCOVER16 | PERCOVER32 | PERCOVER48 |
-------------------------------------------------- --------------
| 2013-01-01 | 一个 | 50 | 0 | 0 |
| 2013-01-01 | 乙 | 100 | 100 | 50 |
| 2013-02-01 | 一个 | 0 | 0 | 0 |
| 2013-02-01 | 乙 | 100 | 50 | 0 |

SQL小提琴

有没有更简单的方法可以使用 CTE 做到这一点?

4

3 回答 3

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(*)or count(c.counter)

另一方面,对于临时代码,我可能只是制作 counter 1.0

于 2013-06-20T17:01:09.333 回答
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;

演示

不要使用1and 0,而是将值更改1.0为小数而不是整数。

或者正如 Gordon 指出的那样,您可以使用 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;
于 2013-06-20T17:04:05.393 回答
5

改变

Sum(c.over16) / Sum(c.counter)

至:

cast(SUM(c.over16) as float) / cast(SUM(c.counter) as float)

(以及所有其他的。)

整数相除得到整数。您需要先转换为浮动。

于 2013-06-20T17:01:23.970 回答