Попытка суммировать псевдонимы для заголовков столбцов с использованием общих табличных выражений - PullRequest
0 голосов
/ 13 января 2019

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

Я хочу посчитать количество попыток в неделю, а также количество проходов и неудач, затем взять сумму этих проходов и неудач в качестве проверки.

SELECT week, 
    COUNT (Week) as weekcount, 

    sum(case when result = 'pass' then 1 else 0 end) as 'passcount' ,
    sum(case when result = 'fail' then 1 else 0 end) as 'failcount',
        sum(case when result = 'pass' then 1 else 0 end) +
        sum(case when result = 'fail' then 1 else 0 end) as 'sum'

FROM table1
group by week
order by week

Приведенный выше фрагмент кода выполняет то, что я хочу, но я читал о CTE как альтернативе повторению в моем запросе.

Я хочу иметь возможность использовать псевдонимы 'passcount' и 'failcount' в своем запросе, не добавляя их в виде столбцов в таблицу. Сначала я попытался настроить CTE.

with sums as
(
    select result,
    sum(case when result = 'pass' then 1 else 0 end) as 'passcount' ,
    sum(case when result = 'fail' then 1 else 0 end) as 'failcount',
    from table1 
)

Выше сообщается о синтаксической ошибке в конце закрывающей скобки, но я не могу понять, почему.

Может кто-нибудь пролить свет на этот или лучший способ приблизиться?

Ответы [ 4 ]

0 голосов
/ 14 января 2019

Я не уверен, почему вы думаете о CTE, вы можете сделать это в одном наборе:

SELECT 
        [Week], 
        COUNT([Week]) AS weekcount
    ,   SUM(CASE WHEN result = 'pass' THEN 1 ELSE 0 END) AS passcount   
    ,   SUM(CASE WHEN result = 'fail' THEN 1 ELSE 0 END) AS failcount
    ,   COUNT(*) AS TotalSum
FROM table1
GROUP BY [Week]

В SQL Server нельзя ссылаться на псевдоним из того же SELECT, например, passcount, weekcount..etc. Для этого вам потребуется обходной путь, например использование подзапроса, CTE, JOIN, CROSS APPLY или любого другого метода, который будет использоваться для этой цели.

Вот некоторые из распространенных методов:

Использование подзапроса :

SELECT 
    [Week]
,   SUM(weekcount) weekcount
,   SUM(passcount) passcount
,   SUM(failcount) failcount
,   SUM(passcount + failcount) AS TotalSum
FROM (
    SELECT 
        [Week], 
        COUNT([Week]) AS weekcount
    ,   SUM(CASE WHEN result = 'pass' THEN 1 ELSE 0 END) AS passcount   
    ,   SUM(CASE WHEN result = 'fail' THEN 1 ELSE 0 END) AS failcount
    FROM table1
    GROUP BY [Week]
) D 
GROUP BY 
    [Week]

Использование CTE метод:

;WITH CTE AS (
    SELECT 
        [Week], 
        COUNT([Week]) AS weekcount
    ,   SUM(CASE WHEN result = 'pass' THEN 1 ELSE 0 END) AS passcount   
    ,   SUM(CASE WHEN result = 'fail' THEN 1 ELSE 0 END) AS failcount
    FROM table1
    GROUP BY [Week]
)
SELECT      
        [Week]
    ,   SUM(weekcount) weekcount
    ,   SUM(passcount) passcount
    ,   SUM(failcount) failcount
    ,   SUM(passcount + failcount) AS TotalSum
FROM CTE 
GROUP BY 
    [Week]

Использование метода CROSS APPLY : Обратитесь к ответу @Gordon Linoff (простой и прямой).

это самые простые методы, которые вы можете использовать в вашем случае. Вы также можете использовать PIVOT в вашем случае, но я не упомянул это для простоты.

0 голосов
/ 13 января 2019

Вам просто нужен еще один выбор после паратезов

with sums as
(
    select result,
    sum(case when result = 'pass' then 1 else 0 end) as 'passcount' ,
    sum(case when result = 'fail' then 1 else 0 end) as 'failcount',
    from table1 
)
select result, passcount, failcount, passcount + failcount as sum
from sums;
0 голосов
/ 13 января 2019

На самом деле вам не нужно писать оба выражения CASE, вы можете просто использовать IN:

SELECT Week,
       COUNT(Week) AS weekcount,
       COUNT(CASE Result WHEN 'pass' THEN 1 END) AS PassCount,
       COUNT(CASE Result WHEN 'fail' THEN 1 END) AS FailCount,
       COUNT(CASE WHEN Result IN ('pass','fail') THEN 1 END) AS PassFailCount
FROM Table1
GROUP BY Week
ORDER BY Week;

Да, это не показывает, как использовать CTE, однако логика «чище» (более краткая), чем повторение обоих CASE выражений.

0 голосов
/ 13 января 2019

В SQL Server я думаю, что боковые объединения (т. Е. cross apply) - более чистый подход, чем подзапросы и CTE. В вашем случае вы можете сгенерировать флаги перед агрегацией, поэтому это выглядит так:

select week, count(*) as weekcount, 
       sum(ispass) as passcount,
       sum(isfail) as failcount,
       (sum(ispass) + sum(isfail)) as passfailcount
from table1 t1 cross apply
     (values (case when result = 'pass' then 1 else 0 end,
              case when result = 'fail' then 1 else 0 end
             )
     ) v(ispass, isfail)
group by week
order by week
...