Я хочу учитывать все записи при подсчете количества для num_zaprosa и num_otveta, но не показывать их в наборе результатов, если одна из них равна нулю. Можно ли сделать это? вот мой код, но он не помог мне решить мою проблему:
WITH counted_records AS (
SELECT num_zaprosa, num_otveta,
COUNT(*) AS count_all_records,
SUM(CASE WHEN num_zaprosa IS NOT NULL THEN 1 ELSE 0 END) AS count_num_zaprosa,
SUM(CASE WHEN num_otveta IS NOT NULL THEN 1 ELSE 0 END) AS count_num_otveta
FROM your_table
GROUP BY num_zaprosa, num_otveta
)
SELECT num_zaprosa, num_otveta, count_all_records, count_num_zaprosa, count_num_otveta
FROM counted_records
WHERE num_zaprosa IS NOT NULL OR num_otveta IS NOT NULL;
исходные данные:
num_zaprosa|num_otveta
______________________
2344 | 200
22 | null
2344 | 200
155 | 6
22 | 9999
какой результат я ожидаю:
num_zaprosa|num_otveta| count_num_zaprosa| count_num_otveta |
_____________________________________________________________
2344 | 200 | 2 | 2 |
_____________________________________________________________
22 | 9999 | 2 | 1 |
_____________________________________________________________
155 | 6 | 1 | 1 |
Обратите внимание, что в таблицах есть строки и столбцы, а не записи или поля.
Можете ли вы добавить примеры данных с ожидаемым результатом? Это действительно прояснит, что вы ищете
Минимальный воспроизводимый пример — отличное начало при обращении за помощью по SQL. (И не отмечайте неиспользуемые продукты. Вы используете и MS SQL Server, и Firebird?)
Я обновил вопрос и показал какой мне нужен результат, так как я плохо сформулировал вопрос
это не имеет смысла, скажем, у вас есть таблица с: {2344, 200; 2344, 201; 2344, ноль}, к какому num_zaprosa | num_otveta
он (ноль) должен относиться?
Вы можете сначала поставить select distinct num_zaprosa
в левой части соединения в качестве основы вашего запроса.
Как только отдельный num_zaprosa
будет идентифицирован, вы можете присоединиться к агрегации, используя num_zaprosa
в качестве отдельного (идентификатора) ключа.
WITH base as (
select distinct num_zaprosa
from `table`
where num_zaprosa IS NOT NULL
)
select
b.num_zaprosa,
max(coalesce(t.num_otveta,0)) as num_otveta,
...
from base as b
left join `table` as t
on b.num_zaprosa = t. num_zaprosa
group by b.num_zaprosa
Один из вариантов — использовать условные аналитические функции Count() Over().
WITH -- S a m p l e D a t a :
tbl AS
( Select 2344 as num_zaprosa, 200 as num_otveta From RDB$DATABASE Union All
Select 22, null From RDB$DATABASE Union All
Select 2344, 200 From RDB$DATABASE Union All
Select 155, 6 From RDB$DATABASE Union All
Select 22, 9999 From RDB$DATABASE
)
-- M a i n S Q L :
SELECT num_zaprosa, num_otveta,
Max(count_num_zaprosa) as count_num_zaprosa,
Max(count_num_otveta) as count_num_otveta
FROM ( Select d.num_zaprosa, d.num_otveta,
Count(Case When t.num_zaprosa = d.num_zaprosa Then 1 End) Over(Partition By t.num_zaprosa, t.num_otveta) as count_num_zaprosa,
Count(Case When t.num_otveta = d.num_otveta Then 1 End) Over(Partition By t.num_zaprosa, t.num_otveta) as count_num_otveta
From ( Select Distinct num_zaprosa, num_otveta
From tbl
) d
Inner Join tbl t ON( (t.num_zaprosa = d.num_zaprosa And t.num_otveta = d.num_otveta)
OR
(t.num_zaprosa = d.num_zaprosa And t.num_otveta Is Null)
)
)
WHERE num_zaprosa Is Not Null And num_otveta Is Not Null
GROUP BY num_zaprosa, num_otveta
/* -- R e s u l t :
NUM_ZAPROSA NUM_OTVETA COUNT_NUM_ZAPROSA COUNT_NUM_OTVETA
----------- ---------- ----------------- ----------------
22 9999 2 1
155 6 1 1
2344 200 2 2 */
См. скрипку здесь.
Это работает, спасибо!!!
Обратите внимание, что в Firebird 4 появилась поддержка стандартного предложения SQL FILTER для агрегатных функций, например. вы можете использовать count(*) filter (where t.num_zaprosa = d.num_zaprosa)
вместо Count(Case When t.num_zaprosa = d.num_zaprosa Then 1 End)
COUNT(num_zaprosa)
будет учитывать только ненулевые значения.