SQL-запрос с функцией to включает только части другого столбца?

#sql #postgresql #unique #where-clause #having

#sql #postgresql #уникальный #where-предложение #имеющий

Вопрос:

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

 fact_order_id
fact_order_line_id
category Group
category Name
  

Я использовал 2 отдельных SQL-запроса ниже. Когда я возвращаюсь и проверяю свою работу, я замечаю, что некоторые fact_order_id в выходных данных не являются заказами только на напитки. Вот 2 отдельных SQL-запроса, которые дают мне одинаковый результат:

 select fact_order_id
from my_table
group by fact_order_id
having avg((category_group like 'Beverage%')::int) = 1;


select fact_order_id
from my_table
group by fact_order_id
having avg(CASE WHEN category_group like 'Beverage%' THEN 1 ELSE 0 END)=1;
  

Оба приведенных выше вывода дают мне одинаковое количество строк. Всякий раз, когда я перепроверяю fact_order_id, некоторые из них будут включать вывод с продуктами питания.

Этот fact_order_id не должен включаться в мои выходные данные, поскольку в заказе есть другие товары, не относящиеся к напиткам. Есть 2 группы категорий, у которых есть название напитка (Напиток (безалкогольный) и напиток (фирменный)). Есть ли лучший способ создания SQL-запроса, чтобы выводить только fact_order_id, которые являются заказами только на напитки?

Я использую версию PostgreSQL: 08.00.0002

Комментарии:

1. Можете ли вы воспроизвести проблему в скрипте: dbfiddle.uk/?rdbms=postgres_9.5

Ответ №1:

Исходя из того, сколько лет вашему PostgreSQL, не могли бы вы, пожалуйста, попробовать это?

 select fact_order_id
  from my_table
 group by fact_order_id
having bool_and((category_group like 'Beverage%'));
  

Основываясь на вашем комментарии, не могли бы вы, пожалуйста, попробовать этот запрос и поделиться своими результатами?

 select fact_order_id, category_group, category_name,
       (category_group like 'Beverage%') as is_beverage
  from my_table
 where fact_order_id = '1 292 757'
  

Вы можете присоединиться обратно к своей таблице в своих проверках, чтобы увидеть, есть ли проблема. Следующий запрос бессмыслен с точки зрения SQL, но он автоматизировал бы вашу перекрестную проверку:

 with bev_orders as (
  select fact_order_id
    from my_table
   group by fact_order_id
  having bool_and((category_group like 'Beverage%'))
)
select *
  from my_table t
  join bev_orders b 
    on b.fact_order_id = t.fact_order_id
 where t.category_group not like 'Beverage%' ;

  

Комментарии:

1. Я по-прежнему получаю тот же точный результат подсчета строк, что и запросы, которые я перечислил выше. Я приму этот ответ, поскольку в этом запросе используется другая функция (bool_and), чем все, что я пробовал раньше.

2. @Natasha Я не понимаю, как это приведет к возврату вашего примера fact_order_id . Вам нет необходимости принимать этот ответ, если он у вас не работает. Я обновил свой ответ запросом, который может помочь нам выяснить, что происходит не так.

3. Значение true / false работает для каждой группы категорий. Я бы не хотел, чтобы это fact_order_id возвращалось в основной SQL-запрос, поскольку в fact_order_id нем есть по крайней мере одно false. При перекрестной проверке я не нашел fact_order_id (пока) в выходных данных, которые включали бы продукт питания.

4. @Natasha Я добавил контрольный запрос к своему ответу.

5. Означает ли вывод «Нет строк для отображения», что исходный запрос правильный?

Ответ №2:

Как насчет исключения fact_order_ids, которые, как вы знаете, не подходят?

 select distinct fact_order_id
from my_table
where fact_order_id not in (
    select distinct fact_order_id
    from my_table
    where not category_group like 'Beverage%'
);
  

Комментарии:

1. У меня есть тысячи строк для моего вывода, поэтому исключение fact_order_id не сработало бы, если бы я не проверил каждый fact_order_id отдельно.

2. Вы меня неправильно поняли. Я предлагаю запрос, который работает путем нахождения обратного тому, что вы ищете, fact_order_ids, в котором есть элемент, не относящийся к напиткам, а затем возвращает все fact_order_ids, которых нет в этом первом наборе.

3. Я получаю тот же точный результат подсчета строк, что и запросы, которые я перечислил выше. Я нахожусь в процессе перекрестной проверки my_table на предмет выходных идентификаторов fact_order_ids, которые вы показали.