【问题标题】:SQL statement with conditions on year带有年份条件的 SQL 语句
【发布时间】:2021-02-23 03:07:35
【问题描述】:

我是 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 的逻辑,有人可以帮忙吗?谢谢。

【问题讨论】:

  • 您的 DBMS 是什么?您应该始终使用您要求的 DBMS 标记 SQL 请求。这些产品的 SQL 方言可能完全不同。
  • 注明@ThorstenKettner

标签: sql select conditional-statements


【解决方案1】:

这是一个非常糟糕的数据模型。数据属于表,而不是数据库结构。年份只是数据(从您的产品表中可以看出),它应该是价格表中的数据。相反,您每年有一个单独的价格表。这使得编写查询很麻烦,如下所示。我建议您更改此数据模型。

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;

【讨论】:

  • 对这两种替代方案进行基准测试会很有趣。
【解决方案2】:

至少可以说,您尝试做的事情很困难。我强烈建议重组您的表格,将所有价格数据放在一个表格中,在该表格中添加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

Demo on db-fiddle

如果您要维护当前的表结构,则可以使用所有UNION 表中的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 表时都必须编辑查询。

Demo on db-fiddle

【讨论】:

  • 是的,就是这样。
  • 它应该是UNION ALL。没有要删除的重复项(这是 UNION [DISTINCT] 的用途)。
  • 是的,替代品(我喜欢我们都有不同的)不太好吃。
  • 谢谢@Nick。我忘了提到我的 procut 表中只有 2020-09-13 的 invoide_date 。我可以将其解析为 YEAR(invoice_date) 。当我添加这样的 pc.year = pr.YEAR(invoice_date) 时出现错误,您能否告诉我如何在上面的查询中添加。非常感谢。
  • @Lilly 应该是pc.year = YEAR(pr.invoice_date)
猜你喜欢
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 2021-11-13
相关资源
最近更新 更多