SQL 数据透视表 Table - 子查询

SQL Pivot Table - Subqueries

我有一个程序可以记录用户在某些方面花费的时间,其中一些被标识为特定 "time"。我正在努力将每个月的多行分组查询结果作为 "summary".

我当前的查询:

SELECT
    TotalMins  = SUM(Minutes)
    ,DateMonth = MONTH(Date)
    ,ID1
    ,PC
FROM User_Time_Log
WHERE
    (UserID = 1)
    AND (YEAR(Date) = 2018)
GROUP BY
    MONTH(Date)
    ,ID1
    ,PC1

当前结果:

TotalMins   DateMonth   ID1         PC1
192         1           0           0
306         1           0           100
113         2           0           0
365         2           0           100
14          2           1           0
3           2           1           100
75          3           0           0
253         3           0           100
3           3           1           0
300         4           0           0
233         4           0           100
10          4           1           0
23          4           1           100
438         5           0           0
134         5           0           100
19          5           1           0
49          5           1           100
0           9           1           0
11          10          0           0
21          10          0           60
167         10          1           100

从这一点开始我想做的是创建一个 table 显示所有 12 个月,无论该月内是否有信息,并在每一行内显示该月的相关信息月。例如:

DateMonth       NonID1      TimeID1     TimePC1 (Round((PC1/100)*TotalMins)) TimePC1ID1
1               192             0               306             0
2               113             14              365             3
3               75              3               253             0
4               300             10              233             23              
5               438             19              134             49
6               0               0               0               0
7               0               0               0               0
8               0               0               0               0   
9               0               0               0               0
10              11              0               13              167
11              0               0               0               0
12              0               0               0               0

最有效的方法是什么?

注意:我还创建了一个 table 来给我 1-12 作为我可以用来给我需要使用的月份的行,其中信息不在 user_time_log.

这里有一个简单的方法来完成您正在寻找的事情:

首先,创建您的 table 月份值。我用单列制作了一个简单的临时 table。

CREATE TABLE #Dates (MonthNum INT)
INSERT INTO #Dates
(
    MonthNum
)
VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)

接下来,您可以将您现有的查询放入一个 CTE,然后 LEFT JOIN 到您的 table 个月。您需要将列放入 SUMCASE 语句中,如下所示:

;WITH Aggregation AS
(
    SELECT
    TotalMins  = SUM(Minutes)
    ,DateMonth = MONTH(Date)
    ,ID1
    ,PC1
FROM #User_Time_Log
WHERE
    (UserID = 1)
    AND (YEAR(Date) = 2018)
GROUP BY
    MONTH(Date)
    ,ID1
    ,PC1
)
SELECT 
    d.MonthNum 
    ,NonID1 = SUM(CASE WHEN ID1 = 0 THEN TotalMins ELSE 0 END)
    ,TimeID1 = SUM(CASE WHEN ID1 = 1 THEN TotalMins ELSE 0 END)
    ,TimePC1 = SUM(CASE WHEN ID1 = 0 THEN ROUND((PC1/100)*TotalMins,0) ELSE 0 END) 
    ,TimePC1ID1 = SUM(CASE WHEN ID1 = 1 THEN ROUND((PC1/100)*TotalMins,0) ELSE 0 END) 
FROM #Dates d
LEFT JOIN Aggregation a ON d.MonthNum = a.DateMonth
GROUP BY d.MonthNum

输出将如下所示:

MonthNum    NonID1  TimeID1 TimePC1 TimePC1ID1
1           498     0       306     0
2           478     17      365     3
3           328     3       253     0
4           533     33      233     23
5           572     68      134     49
6           0       0       0       0
7           0       0       0       0
8           0       0       0       0
9           0       0       0       0
10          32      167     0       167
11          0       0       0       0
12          0       0       0       0

编辑:

ROUND() 函数调用可以稍微更改以适应您对小数结果的需要。 ROUND()的第一个参数是要四舍五入的表达式,第二个参数是要四舍五入到的小数位数。正数表示小数点右边要四舍五入的位数。负数表示小数点左边要四舍五入的位数。因此,如果您将其设置为 2,您将得到四舍五入到最接近的百分之一的答案。

但我们还需要进行一项调整。 PC1TotalMins 在我的回答中都被假定为 INTs。所以我们必须给 SQL 引擎一点帮助,让它计算出 DECIMAL 的答案。通过 CAST()INTs 转换为 DECIMALs,SQL 将执行算术运算作为十进制数学而不是整数数学。您只需要像这样更改 TimePC1TimePC1ID1

,TimePC1 = SUM(CASE WHEN ID1 = 0 THEN ROUND((CAST(PC1 AS DECIMAL)/100)*CAST(TotalMins AS DECIMAL),2) ELSE 0 END) 
,TimePC1ID1 = SUM(CASE WHEN ID1 = 1 THEN ROUND((CAST(PC1 AS DECIMAL)/100)*CAST(TotalMins AS DECIMAL),2) ELSE 0 END) 

然后输出如下所示:

MonthNum    NonID1  TimeID1 TimePC1     TimePC1ID1
1           498     0       306.000000  0.000000
2           478     17      365.000000  3.000000
3           328     3       253.000000  0.000000
4           533     33      233.000000  23.000000
5           572     68      134.000000  49.000000
6           0       0       0.000000    0.000000
7           0       0       0.000000    0.000000
8           0       0       0.000000    0.000000
9           0       0       0.000000    0.000000
10          32      167     12.600000   167.000000
11          0       0       0.000000    0.000000
12          0       0       0.000000    0.000000