Условие SQL, охватывающее несколько строк - PullRequest
0 голосов
/ 17 декабря 2018

Я работаю над системой заказов, основанной на базе данных PostgreSQL, поэтому у меня есть таблица OrderLines следующего вида:

order_id     int
product_id   int
quantity     int

Каждый заказ состоит из одной строки в этомтаблица для каждого заказанного уникального продукта.

Я пытаюсь выполнить запросы в форме:

  • Для каждого заказа, содержащего продукты A, B и C, дайте мне количествадля продуктов C и D
  • Для каждого заказа, содержащего продукты A и (B или C), укажите количества для продукта D
  • Дляв каждом заказе, содержащем продукты A и не менее 2 * B, укажите количества для A, B и C

Условие здесь потенциально может иметь глубоко вложенные пункты.Могут быть миллионы заказов и 10 тыс. + Строк на заказ.Условия не могут быть известны заранее.Если товара нет в заказе, его количество должно быть возвращено как 0.

Есть ли у вас какие-либо указания относительно написания запросов с условиями, которые охватывают несколько строк, таких как эта?

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

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

with summary as (
  select
    order_id,
    sum (case when product_id = 'A' then quantity else 0 end) as a,
    sum (case when product_id = 'B' then quantity else 0 end) as b,
    sum (case when product_id = 'C' then quantity else 0 end) as c,
    sum (case when product_id = 'D' then quantity else 0 end) as d
  from table
  where quantity != 0
  group by order_id
)

(Примечание: вы сказали, что product_id - это целое число, но перечисленные значения являются текстовыми- Я предполагаю, что есть разумное объяснение, но я не пытался согласовать это)

Вы можете использовать это в качестве основы для ответа на каждый из трех вопросов:

Для каждого заказа, содержащегопродукты A, B и C, дайте мне количества для продуктов C и D

select order_id, c, d
from summary
where a > 0 and b > 0 and c > 0

Для каждого заказа, содержащего продукты A и (B или C), дайте мне количества для продукта D

select order_id, d
from summary
where a > 0 and (b > 0 or c > 0)

Для каждого заказа, содержащего продукты A и не менее 2 * B, дайте мне количества для A, B и C

select order_id, a, b, c
from summary
where a > 0 and (a + b + c + d > 2 * b)

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

Если пример условный и на самом деле существует сотни или более номеров элементов, то я бы пропустил CTE / vieи построить каждый случай с соответствующим сценарием.

0 голосов
/ 17 декабря 2018

Вы можете использовать условное агрегирование.Например, для первого:

Для каждого заказа, содержащего продукты A, B и C, укажите количества для продуктов C и D

select order_id,
       sum(quantity) filter (where product_id = C) as c_quantity,
       sum(quantity) filter (where product_id = D) as d_quantity
from orderlines ol
group by order_id
having count(*) filter (where product_id = A) > 0 and
       count(*) filter (where product_id = B) > 0 and
       count(*) filter (where product_id = C) > 0 ;

Другие вопросыможет обрабатываться с подобной логикой, изменяя условия having или sum() s.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...