Инструкция SQL с условиями для года

#sql #select #conditional-statements

#sql #выберите #условные операторы

Вопрос:

Я новичок в SQL и пытаюсь добавить условия в свой SQL-запрос.

У меня есть 4 файла с ценами на продукты за каждый год и еще одна таблица для продуктов.

 price_table_2020
price_table_2019
price_table_2019
  

Все таблицы содержат следующие данные

price_table_2020 :

 product  price   product_description
-------------------------------------
ball      100    plastic ball
ink        80    ink for pen
pen      1000    pen
bucket    200    bucket
  

price_table_2019 :

 product  price   product_description
------------------------------------
ball      90     plastic ball
ink       70     ink for pen
pen      900     pen
bucket   100     bucket
  

price_table_2018 :

 product  price   product_description
-------------------------------------
ball      80     plastic ball
ink       60     ink for pen
pen      800     pen
bucket   300     bucket
  

Таблица продуктов выглядит следующим образом:

 product invoice_year
---------------------
pen     2019
ball    2020
ink     2020
  

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

Ожидаемый результат, как показано ниже:

 product invoice_year   price
----------------------------
pen     2019           900
ball    2020           100
ink     2020            80
  

Я могу получить цену из одной из таблиц, как показано ниже

 select A.price, B.product, B.product_description 
from product A 
inner join price_table_2020 B on A.product = B.product
  

Может кто-нибудь помочь, как это сделать, если мне нужно включить логику, основанную на product.invoice_year ? Спасибо.

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

1. Какова ваша СУБД? Вы должны всегда помечать SQL-запросы с помощью СУБД, для которой вы их запрашиваете. Продукты могут сильно отличаться по своим диалектам SQL.

2. Отметил @ThorstenKettner

Ответ №1:

То, что вы пытаетесь сделать, по меньшей мере сложно. Я бы настоятельно рекомендовал реструктурировать ваши таблицы, чтобы поместить все данные о ценах в одну таблицу, добавив year в эту таблицу столбец, чтобы указать, к какому году применима цена. Тогда ваш запрос становится простым:

 SELECT pr.product,
       pr.invoice_year,
       pc.price
FROM product pr
JOIN price_table pc ON pc.product = pr.product
                   AND pc.year = pr.invoice_year
ORDER BY pr.invoice_year, pr.product
  

Вывод (для ваших выборочных данных):

 product     invoice_year    price
pen         2019            900
ball        2020            100
ink         2020            80
  

Демонстрация в db-fiddle

Если вам нужно сохранить текущую структуру таблицы, вы можете эмулировать price приведенную выше таблицу, используя a UNION из всех price таблиц:

 SELECT pr.product,
       pr.invoice_year,
       pc.price
FROM product pr
JOIN (
  SELECT *, 2020 AS year
  FROM price_table_2020
  UNION ALL
  SELECT *, 2019
  FROM price_table_2019
  UNION ALL
  SELECT *, 2018
  FROM price_table_2018
) pc ON pc.product = pr.product
    AND pc.year = pr.invoice_year
ORDER BY pr.invoice_year, pr.product
  

Результат этого запроса тот же. Недостатком этого подхода является то, что вам приходится редактировать запрос каждый раз, когда вы добавляете новую price таблицу.

Демонстрация в db-fiddle

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

1. Да, это правильный путь.

2. Это должно быть UNION ALL так. Нет дубликатов для удаления (для чего UNION [DISTINCT] и предназначен).

3. Да, альтернативы (мне нравится, что у нас обоих разные) не очень приемлемы.

4. Спасибо @Nick. Я забыл упомянуть, что у меня есть только invoide_date в 2020-09-13 в моей таблице procut. Я мог бы проанализировать его как YEAR (invoice_date) . Я получаю сообщение об ошибке, когда добавляю вот так pc.year = pr.YEAR(invoice_date) Не могли бы вы рассказать мне, как добавить в это приведенный выше запрос. Большое вам спасибо.

5. @Lilly это должно быть pc.year = YEAR(pr.invoice_date)

Ответ №2:

Это очень плохая модель данных. Данные принадлежат таблицам, а не структуре базы данных. Год — это просто данные (как видно из вашей таблицы продуктов), и это должны быть данные в таблице цен. Вместо этого у вас есть отдельная таблица цен за год. Это делает написание запросов неудобным, как видно ниже. Я рекомендую вам изменить эту модель данных.

 select p.*, coalesce(p2018.price, p2019.price, p2020.price) as invoice_price
from products p
left join price_table_2018 p2018 on p2018.product = p.product and p.invoice_year = 2018
left join price_table_2019 p2019 on p2019.product = p.product and p.invoice_year = 2019
left join price_table_2020 p2020 on p2020.product = p.product and p.invoice_year = 2020
order by p.product;
  

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

1. Было бы интересно сравнить две альтернативы.