Сводная таблица SQL - подзапросы - PullRequest
0 голосов
/ 09 октября 2018

У меня есть программа, которая регистрирует время, которое пользователь тратит на определенные аспекты, некоторые идентифицируются как определенное «время».Я изо всех сил пытаюсь получить несколько строк результатов сгруппированных запросов в одну строку для каждого месяца в качестве «сводки».

Мой текущий запрос:

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 голосов
/ 09 октября 2018

Вот простой способ сделать то, что вы ищете:

Сначала создайте таблицу значений месяца.Я сделал простую временную таблицу с одним столбцом.

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

РЕДАКТИРОВАТЬ:

Вызов функции ROUND() может быть слегка изменен, чтобы удовлетворить ваши потребности в десятичных результатах.Первый параметр ROUND() - это выражение, которое вы хотите округлить, а второй - количество десятичных разрядов для округления.Положительные числа указывают количество мест справа от десятичного знака до округления до.Отрицательные числа указывают количество мест слева от десятичной дроби до округления до.Поэтому, если вы установите значение 2, вы получите ответ, округленный до сотых.

Но нам нужен еще один твик.PC1 и TotalMins оба предполагаются равными INT s в моем ответе.Поэтому нам нужно немного помочь движку SQL, чтобы он вычислял ответ как DECIMAL.От CAST() с INT с до DECIMAL с 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.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
...