Оператор CASE, когда критерии находятся в разных строках и столбцах - PullRequest
2 голосов
/ 02 марта 2020

DB Fiddle

CREATE TABLE sales (
    campaign VARCHAR(255),
    event_type VARCHAR(255),
    event_date VARCHAR(255),
    quantity VARCHAR(255)
);

INSERT INTO sales
(campaign, event_type, event_date, quantity)
VALUES 
("C001", "buy", "2019-05-08", "500"),
("C001", "sale", "2019-04-20", "400"),

("C002", "buy", "2019-06-07", "800"),
("C002", "sale", "2019-06-15", "900"),

("C003", "buy", "2020-02-23", "700"),
("C003", "sale", "2020-03-17", "300"),

("C004", "buy", "2020-04-05", "200"),
("C004", "sale", "2020-03-17", "600");

В таблице отображаются event_types (buy, sell) и соответствующие quantities за campaign.


Теперь я хочу запустить query, который проверяет следующее:

a) event_date для event_type buy> event_date для event_type sell
b) quantity для event_type buy> quantity для event_type sell

Результат должен выглядеть следующим образом:

campaign     Check_Date     Check_Quantity
C001            Error            OK
C002            OK              Error
C004            OK              Error

Я думаю, мне нужно go с оператором CASE, примерно так:

SELECT
campaign, 
(CASE WHEN event_date of buy > event_date of sale THEN "Error" ELSE "OK") AS Check_Date,
(CASE WHEN quantity of buy > quantity of sale THEN  "Error" ELSE "OK") AS Check_Quantity
quantity
FROM sales;

Ответы [ 4 ]

2 голосов
/ 02 марта 2020

Вы хотите сравнить значения по строкам, так что это предполагает агрегирование. Затем вы можете реализовать logi c с case выражениями:

select
    campaign, 
    case when 
        max(case when event_type = 'buy' then event_date end) 
            > max(case when event_type = 'sale' then event_date end)
            then 'OK'
            else 'Error'
    end check_date,
    case when 
        max(case when event_type = 'buy' then quantity end) 
            > max(case when event_type = 'sale' then quantity end)
            then 'OK'
            else 'Error'
    end check_date
from sales
group by campaign;

In ваша БД Fiddle , это дает:

campaign | check_date | check_date
:------- | :--------- | :---------
C001     | OK         | OK        
C002     | Error      | Error     
C003     | Error      | OK        
C004     | OK         | Error     
1 голос
/ 02 марта 2020
SELECT t1.campaign, 
       CASE WHEN t1.event_date > t2.event_date
            THEN 'OK'
            ELSE 'Error'
            END Check_Date,
       CASE WHEN t1.quantity > t2.quantity
            THEN 'OK'
            ELSE 'Error'
            END Check_Quantity
FROM sales t1
JOIN sales t2 USING ( campaign )
WHERE t1.event_type = 'buy'
  AND t2.event_type = 'sale';

fiddle

Чтобы результат был значимым, вы ДОЛЖНЫ добавить уникальный индекс с помощью (campaign, event_type) и ограничить список значений безопасным для поля event_type (сделать его ENUM?) .

Также вы не указали, что должно быть возвращено для кампании, если для нее существует только одна запись - мой запрос вообще не будет возвращать такую ​​кампанию.

1 голос
/ 02 марта 2020

Разделите таблицу на 2 запроса, затем присоединитесь и используйте выражения CASE:

select
  b.campaign,
  case when b.event_date > s.event_date then 'Error' else 'OK' end Check_Date,
  case when b.quantity > s.quantity then 'Error' else 'OK' end Check_Quantity
from (select * from sales where event_type = 'buy') b
inner join (select * from sales where event_type = 'sale') s
on s.campaign = b.campaign

См. Демонстрационную версию . Результаты:

> campaign | Check_Date | Check_Quantity
> :------- | :--------- | :-------------
> C001     | Error      | Error         
> C002     | OK         | OK            
> C003     | OK         | Error         
> C004     | Error      | OK           
1 голос
/ 02 марта 2020

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

select t.campaign, 
       (case when buy_dt > sale_dt then 'OK' else 'Error' end) as Check_date,
       (case when buy_qty > sale_qty then 'OK' else 'Error' end) as Check_qty
from (select s.campaign, 
             max(case when s.event_type = 'buy' then s.event_date end) as buy_dt,
             max(case when s.event_type = 'sale' then s.event_date end) as sale_dt,
             max(case when s.event_type = 'buy' then s.quantity end) as buy_qty,
             max(case when s.event_type = 'sale' then s.quantity end) as sale_qty
      from sales s
      group by s.campaign 
     ) t;
...