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

Я хочу учитывать все записи при подсчете количества для 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       |
COUNT(num_zaprosa) будет учитывать только ненулевые значения.
jarlh 02.07.2024 21:20

Обратите внимание, что в таблицах есть строки и столбцы, а не записи или поля.

jarlh 02.07.2024 21:21

Можете ли вы добавить примеры данных с ожидаемым результатом? Это действительно прояснит, что вы ищете

Error_2646 02.07.2024 21:22

Минимальный воспроизводимый пример — отличное начало при обращении за помощью по SQL. (И не отмечайте неиспользуемые продукты. Вы используете и MS SQL Server, и Firebird?)

jarlh 02.07.2024 21:23

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

John B 02.07.2024 21:43

это не имеет смысла, скажем, у вас есть таблица с: {2344, 200; 2344, 201; 2344, ноль}, к какому num_zaprosa | num_otveta он (ноль) должен относиться?

Jorge Campos 02.07.2024 23:28
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
6
83
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете сначала поставить 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    */

См. скрипку здесь.

Это работает, спасибо!!!

John B 04.07.2024 08:55

Обратите внимание, что в 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)

Mark Rotteveel 04.07.2024 09:20

Другие вопросы по теме