#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
Если вам нужно сохранить текущую структуру таблицы, вы можете эмулировать 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
таблицу.
Комментарии:
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. Было бы интересно сравнить две альтернативы.