在SQL Server中将行值转换为列名
我找不到问题的答案,这几天我都在为这个问题绞尽脑汁 基本上我有3张桌子:在SQL Server中将行值转换为列名,sql,sql-server,pivot,Sql,Sql Server,Pivot,我找不到问题的答案,这几天我都在为这个问题绞尽脑汁 基本上我有3张桌子: Receipt, Receiptline, Receiptlinedetail 简要总结这三个原因: 收据-所有收据的列表(例如:收据100) 收据行-收据的每一行(例如:收据100已通过Visa支付) Receiptlinedetail—receiptline的详细信息(例如:NetAmount的售价为50欧元) 现在,我想有一个横向的概述,所有已完成的付款,每天 输出应如下所示: Day | Visa
Receipt, Receiptline, Receiptlinedetail
简要总结这三个原因:
- 收据-所有收据的列表(例如:收据100)
- 收据行-收据的每一行(例如:收据100已通过Visa支付)
- Receiptlinedetail—receiptline的详细信息(例如:NetAmount的售价为50欧元)
Day | Visa | Mastercard | Cash
2020-11-30 20.00 10.00 5.00
我的数据:
表收据
:
ReceiptId ReceiptNumber ReceiptType ReceiptDateTime ModifiedKind
----------------------------------------------------------------------------
44919 1 100 2020-08-15 13:49:45.633 100
44920 1 200 2020-08-15 13:50:15.060 100
44921 2 100 2020-08-15 13:54:14.007 100
44922 2 300 2020-08-15 13:55:31.650 100
44923 3 100 2020-08-15 13:55:38.263 100
44924 3 300 2020-08-15 13:56:47.677 100
44925 4 100 2020-08-15 13:56:58.940 100
44926 4 200 2020-08-15 13:57:13.707 100
表接收行:
ReceiptLineId ReceiptId LineType ItemId Description Quantity ModifiedKind
----------------------------------------------------------------------------------------
89471 44919 300 0 GlobalInfo 1.0000 100
89472 44920 100 225 Sprite 4.0000 100
89473 44920 200 3 Cash 1.0000 100
89474 44920 300 0 GlobalInfo 1.0000 100
89475 44921 300 0 GlobalInfo 1.0000 100
89476 44922 300 0 GlobalInfo 1.0000 100
89477 44923 300 0 GlobalInfo 1.0000 100
89478 44924 300 0 GlobalInfo 1.0000 100
89479 44925 300 0 GlobalInfo 1.0000 100
89480 44926 200 6 VISA 1.0000 100
表receiptlinedetail
:
ReceiptLineDetailId ReceiptLineId LineType ItemId Description Quantity NetAmount ModifiedKind
---------------------------------------------------------------------------------------------------------
89493 89471 300 0 GlobalInfo 1.0000 0.00 100
89494 89472 100 225 Sprite 4.0000 8.00 100
89495 89473 200 3 Cash 1.0000 -8.00 100
89496 89474 300 0 GlobalInfo 1.0000 0.00 100
89497 89475 300 0 GlobalInfo 1.0000 0.00 100
89498 89476 300 0 GlobalInfo 1.0000 0.00 100
89499 89477 300 0 GlobalInfo 1.0000 0.00 100
89500 89478 300 0 GlobalInfo 1.0000 0.00 100
89501 89479 300 225 Sprite 1.0000 2.00 100
89502 89482 300 0 GlobalInfo 1.0000 0.00 100
89503 89480 200 6 VISA 1.0000 -2.00 100
我还有一个付款表,其中列出了所有不同的付款选项
PaymentId Description PaymentType ModifiedKind
----------------------------------------------------
1 Diners Club 200 200
2 Mastercard 200 200
3 Cash 100 200
4 Mobile payment 100 200
5 Shopmaster 500 200
6 VISA 200 200
小结:
收据中的所有付款均为“线型200”。付款方式的金额可能因数据库而异,但总是列在付款表中。我认为通过项目ID
列可以链接到付款。剩下的只是连接和条件聚合:
select convert(date, r.ReceiptDateTime),
sum(case when p.Description = 'Visa' then rld.net_amount else 0 end) as visa,
sum(case when p.Description = 'MasterCard' then rld.net_amount else 0 end) as mastercard,
sum(case when p.Description = 'Cash' then rld.net_amount else 0 end) as cash
from receipt r join
receiptline rl
on rl.ReceiptId = r.ReceiptId join
receiptlinedetail rld
on rld.ReceiptLineId = rl.ReceiptLineId join
payments p
on p.paymentid = rl.itemid and rl.LineType = 200
group by convert(date, r.ReceiptDateTime)
我想到的唯一方法是使用动态SQL进行数据透视
试试这个:
DECLARE @columns VARCHAR(MAX) = '';
declare @sql NVARCHAR(MAX) = '';
SELECT
@columns+=QUOTENAME(Description) + ','
FROM
payment
ORDER BY
Description;
SET @columns = LEFT(@columns, LEN(@columns) - 1);
SET @sql = '
select *
from(
select convert(date, r.ReceiptDateTime) as Day,
p.Description,
rld.netamount
from receipt r
join receiptline rl
on rl.ReceiptId = r.ReceiptId
join receiptlinedetail rld
on rld.ReceiptLineId = rl.ReceiptLineId
join payment p
on p.paymentid = rl.itemid and rl.LineType = 200
) d pivot (
sum(netamount)
for Description in (' + @columns + ')
) as t;'
EXECUTE sp_executesql @sql;
我看不出有什么办法把付款和收据联系起来。关于这一点,你的问题需要更清楚。为什么付款表没有日期或收据id?我可以理解您的问题,收据和付款之间的链接在itemid中,具体取决于线型。例如,付款id 6=visa,itemid=6就是指这个。这是POS(销售点)/收银机的数据库。因此,收据/账单可以通过不同的支付方式进行支付,例如50%的现金和50%的VISA卡支付。用户可以定义不同的付款方式。我希望这是清楚的我希望它是那么简单,不幸的是硬编码的付款说明是不够好。因为它们不是“标准”。可以有一个客户不使用“VISA”支付方式,或者我们可以有比现在更多的支付方式table@Steven . . . 这确实回答了您提出的问题。