Sql server SQL数据透视表-子查询

Sql server SQL数据透视表-子查询,sql-server,join,nested-query,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)

我有一个程序,记录用户在某些方面花费的时间,有些被确定为特定的“时间”。我很难将多行分组查询结果作为“摘要”每个月都放在一行中

我当前的查询:

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 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 DateMonth非ID1时间ID1时间PC1(整数((PC1/100)*总分钟))时间PC1ID1 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行,我可以使用它为我提供我需要使用的月份,其中的信息不在用户时间日志中。

以下是一个简单的方法来完成您需要的操作:

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

CREATE TABLE #Dates (MonthNum INT)
INSERT INTO #Dates
(
    MonthNum
)
VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
接下来,您可以将现有查询放入CTE,然后
左键联接到月份表中。您需要将列放入
SUM
'd
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
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
编辑:

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

但我们还需要一个调整<在我的回答中,code>PC1
TotalMins
都假定为
INT
s。因此,我们必须给SQL引擎一点帮助,以便它将答案计算为
十进制数。通过
CAST()
INT
s转换为
DECIMAL
s,SQL将以十进制数学而不是整数数学的形式执行算术运算。您只需更改
TimePC1
TimePC1ID1
如下:

,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     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
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

听起来你知道你需要做什么。使用包含12行的表作为查询的基础,并左键连接到其他用户\u时间\u日志表查询。只需将where子句移动到join谓词。谢谢您的帮助。我似乎对这个计算的圆形部分有另一个困难。我有一个31分钟的数字,四舍五入60%,但结果是0。我尝试将百分比计算和“圆形”括号内的所有内容都转换为小数点后两位,但仍然只返回0。有什么建议吗?谢谢你。只需将轮的外部转换为int,即可将其恢复为整数。再次感谢你!