SQL数据透视表-子查询

时间:2018-10-09 15:50:56

标签: sql-server join nested-query

我有一个程序可以记录用户在某些方面花费的时间,其中一些被标识为特定的“时间”。我正在努力使多行分组查询结果的每一行作为“摘要”进入每个月。

我当前的查询:

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

从现在开始,我想创建一个表来显示所有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

最有效的方法是什么?

注意:我还创建了一个表,给我1-12个行,可以用来给我提供我需要使用的月份,其中信息不在user_time_log内。

1 个答案:

答案 0 :(得分:1)

这是做您想要的事情的简单方法:

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

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放入月度表。您需要将列放入SUM的{​​{1}}语句中,如下所示:

CASE

输出将如下所示:

;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(),则会得到四舍五入到最接近的百分数的答案。

但是我们还需要进行一些调整。我的答案中假设2PC1都是TotalMins。因此,我们必须给SQL引擎一些帮助,以便它将答案计算为INT。通过将DECIMAL设置为CAST(),SQL将把算术运算作为十进制数学运算而不是整数数学运算。您只需要像这样更改INTDECIMAL

TimePC1

然后输出看起来像这样:

TimePC1ID1