Возвращает строку для GROUP BY CASE, когда NULL THEN THEN (...) ELSE (...), даже если запись не существует - PullRequest
0 голосов
/ 17 октября 2019

Давайте рассмотрим следующий сценарий.

CREATE TABLE Replicant (Name NVARCHAR(10),Gen INT);
INSERT INTO Replicant VALUES ('tymtam', 2), ('Roy', 6);

SELECT   
    CASE WHEN Gen < 10 THEN '<10' ELSE '>=10' END as 'Gen', 
    count(*) as 'Count' 
FROM Replicant
GROUP BY CASE WHEN Gen < 10 THEN '<10' ELSE '>=10' END;

Результат представляет собой одну строку:

Gen Count
<10 2

Могу ли я усовершенствовать запрос, чтобы получить ноль для ELSEcase?

Gen  Count
<10  2
>=10 0

Обновление 2

Мой дискриминатор имеет значение 'null'

SELECT   CASE WHEN Gen IS NOT NULL THEN 'Known' ELSE 'Unknown' END as 'Gen', count(*) as 'Count' FROM Replicant
GROUP BY CASE WHEN Gen IS NOT NULL THEN 'Known' ELSE 'Unknown' END;

Результат

Gen     Count
Known   2

и я тоскую по

Gen     Count
Known   2
Unknown 0

Обновление 1

В моем контексте у меня есть пары запросов (метрик) для разных поколений репликантов:

INSERT INTO [dbo].[Metrics] (...) SELECT
'Metric X for >=10' as 'Name',
COUNT(*) AS 'Count',
(80_char_expression) AS 'Sum',
(80_char_expression) AS 'Min',
(80_char_expression) AS 'Max', 
0 AS 'StandardDeviation'
FROM Replicant  
WHERE TimestampUtc > DATEADD(WEEK, -1, Current_Timestamp)
AND Gen >= 10

INSERT INTO [dbo].[Metrics] (...) SELECT
'Metric X for <10' as 'Name',
--7 lines repeated from the 1st query
AND Gen < 10

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

Ответы [ 2 ]

0 голосов
/ 17 октября 2019

Вы можете использовать left join:

SELECT v.Gen, COUNT(r.gen) as cnt
FROM (VALUES (NULL, 10, '<10'),
             (10, NULL, '>=10')
     ) v(lo, hi, gen) LEFT JOIN
     Replicant r
     ON (r.gen >= v.lo OR v.lo IS NULL) AND
        (r.gen < v.hi OR v.hi IS NULL)
GROUP BY v.gen;

Вы также можете использовать условное агрегирование и разворачивание:

select v.*
from (select sum(case when r.gen < 10 then 1 else 0 end) as gen_1,
             sum(case when r.gen >= 10 then 1 else 0 end) as gen_2
      from replicant r
     ) r cross apply
     (values (gen_1, '<10'), (gen_2, '>=10')
     ) v(cnt, gen);
0 голосов
/ 17 октября 2019

Вы можете попытаться использовать UNOIN ALL, составьте таблицу сравнения для своего счета, затем выполните outer join

Запрос 1 :

SELECT t1.word,
       COUNT(Name) 'Count'
FROM
(
SELECT '<10' word,9 maxval,0 minval
UNION ALL
SELECT '>=10' word,2147483646 maxval,10 minval
) t1 LEFT JOIN Replicant on Gen BETWEEN t1.minval AND t1.maxval
GROUP BY t1.word

Результаты :

| word | Count |
|------|-------|
|  <10 |     2 |
| >=10 |     0 |
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...