SQL Server:连接数据但在单行中
Posted
技术标签:
【中文标题】SQL Server:连接数据但在单行中【英文标题】:SQL Server: join data but in single row 【发布时间】:2021-08-10 13:01:10 【问题描述】:我有一张表Invoice
,看起来类似于:
order_id | completed_at | subtotal | discount_amount | handling_amount |
---|---|---|---|---|
100 | 07/01/2021 | 10.09 | 0 | 0 |
101 | 07/04/2021 | 200.30 | 0 | 0 |
102 | 07/04/2021 | 54.10 | 0 | 0 |
103 | 07/06/2021 | 12.00 | 0 | 0 |
我还有一张桌子InvoiceDetail
:
order_id | product_id | qty | amount |
---|---|---|---|
100 | 1234 | 1 | 1.09 |
100 | Shipping1 | 1 | 4.30 |
100 | SalesTax | 1 | .67 |
101 | 987 | 2 | 74.20 |
101 | 654 | 1 | 6.20 |
101 | Shipping2 | 1 | 5.10 |
101 | SalesTax | 1 | 2.30 |
102 | 123 | 1 | 30.15 |
102 | Shipping8 | 1 | 6.80 |
102 | SalesTax | 1 | 1.08 |
103 | 321 | 1 | 8.04 |
103 | Shipping4 | 1 | 2.05 |
103 | SalesTax | 1 | .70 |
我需要加入表格,如下所示:
order_id | completed_at | subtotal | shipping | sales_tax | discount_amount | handling_amount |
---|---|---|---|---|---|---|
100 | 07/01/2021 | 10.09 | 4.30 | .67 | 0 | 0 |
101 | 07/04/2021 | 200.30 | 5.10 | 2.30 | 0 | 0 |
102 | 07/04/2021 | 54.10 | 6.80 | 1.08 | 0 | 0 |
103 | 07/06/2021 | 12.00 | 2.05 | .70 | 0 | 0 |
我尝试了几种不同的方法,但每次都以每个 order_id 多行结束。
SELECT
order_id,
completed_at,
subtotal,
CASE
WHEN t2.product_id LIKE '%Shipping%'
THEN t2.amount
END AS shipping,
CASE
WHEN t2.product_id = 'SalesTax'
THEN t2.amount
END AS sales_tax,
discount_amount,
handling_amount
FROM
Invoice t1
INNER JOIN
InvoiceDetail t2 ON t1.order_id = t2.InvoiceDetail
WHERE
order_id BETWEEN '100' AND '103'
上面将输出信息,但每个order_id
都在多行中。我需要将订单信息与运费和销售税结合在一起。如何实现我的目标?
【问题讨论】:
如果可以的话,您可能需要重新考虑您的表架构。如果您将诸如运费和销售税之类的内容转换为单个实际产品的列,我认为您的时间会轻松得多。我希望那些只会有 1 的数量,因此您不仅会使您的查询更加困难,而且您还增加了额外的处理能力来计算您应该存储的值。 您可以为每一列执行左连接,或者 PIVOT 是您要查找的关键字 【参考方案1】:您已经很接近了,您只需要在InvoiceDetail
的字段周围使用SUM()
,然后在Invoice
的字段周围使用GROUP BY
:
SELECT i.order_id,
i.completed_at,
i.subtotal,
SUM(CASE WHEN id.product_id LIKE '%Shipping%' THEN id.Amount END) AS shipping,
SUM(CASE WHEN id.product_id = 'SalesTax' THEN id.Amount END) AS sales_tax,
i.discount_amount,
i.handling_amount
FROM dbo.Invoice AS i
INNER JOIN dbo.InvoiceDetail AS id
ON id.order_id = i.order_id
WHERE i.order_id BETWEEN 100 AND 103
GROUP BY i.order_id, i.completed_at, i.subtotal, i.discount_amount, i.handling_amount;
注意,我从 t1.order_id = t2.InvoiceDetail
更新了您的连接条件,因为这看起来像是问题中的错误,可能是两个表中的 order_id
。
我还删除了 100
和 103
周围的引号。如果order_id
是整数,则不需要引号,如果order_id
不是整数,则BETWEEN
可能不适合使用。
与您的问题无关,但是对于 SQL Server,养成always including the schema prefix 的习惯是一个好主意(除了您真正想根据执行上下文切换架构的情况)。另一个好习惯是use meaningful table aliases。如果您使用t1
、t2
、t3
等,当您有大量查询时,这很快就会变得非常混乱,t4
不会给我任何关于它可能是哪个表的信息,但是如果您使用与表本身(例如,i
用于发票,id
用于发票详细信息),然后在阅读代码时更清楚哪一列来自哪个表。
【讨论】:
【参考方案2】:您可以在SUM()
聚合函数中使用CASE
来使用条件聚合。例如:
select
i.order_id,
max(i.completed_at) as completed_at,
max(i.subtotal) as subtotal,
sum(case when d.product_id like 'Shipping%' then amount end) as shipping,
sum(case when d.product_id = 'SalesTax' then amount end) as sales_tax,
max(i.discount_amount) as discount_amount,
max(i.handling_amount) as handling_amount
from invoice i
left join invoicedetail d on d.order_id = i.order_id
group by i.order_id
【讨论】:
以上是关于SQL Server:连接数据但在单行中的主要内容,如果未能解决你的问题,请参考以下文章
Microsoft SQL Server 查询连接数和关闭连接数
vs 或 Sql server2012连接Sql server时出现的问题:已成功与服务器建立连接,但在登陆过程中发生错误
vs 或 Sql server2012连接Sql server时出现的问题:已成功与服务器建立连接,但在登陆过程中发生错误
vs 或 Sql server2012连接Sql server时出现的问题:已成功与服务器建立连接,但在登陆过程中发生错误