【问题标题】:how to use "Stuff and 'For Xml Path'" to unite rows in table如何使用“Stuff and 'For Xml Path'”来合并表格中的行
【发布时间】:2021-05-19 17:46:09
【问题描述】:

请帮我在表格中获取统一的行和用​​逗号分隔的帐户列表。我不太明白如何使用“Stuff and 'For Xml Path'”。

这是我的查询:

CREATE TABLE invoices
(
invoice VARCHAR(20) NOT NULL,
quantity INT NOT NULL,
price INT NOT NULL,
summ INT NOT NULL, 
account INT NOT NULL,
);
INSERT invoices(invoice, quantity, price, summ, account) 
VALUES ('ty20210110', 2, 100, 200, 1001);
INSERT invoices(invoice, quantity, price, summ, account) 
VALUES ('ty20210110', 3, 100, 300, 1002);
INSERT invoices(invoice, quantity, price, summ, account) 
VALUES ('ty20210110', 1, 250, 250, 1001);
INSERT invoices(invoice, quantity, price, summ, account) 
VALUES ('ty20210110', 2, 120, 240, 1002);
INSERT invoices(invoice, quantity, price, summ, account) 
VALUES ('ty20210110', 4, 100, 400, 1002);
INSERT invoices(invoice, quantity, price, summ, account) 
VALUES ('ty20210114', 3, 100, 300, 1001);
INSERT invoices(invoice, quantity, price, summ, account) 
VALUES ('ty20210114', 5, 80, 400, 1003);
INSERT invoices(invoice, quantity, price, summ, account) 
VALUES ('ty20210114', 5, 100, 500, 1004);


SELECT invoices.invoice, invoices.summ,  accounts = STUFF(
             (SELECT DISTINCT ',' + Convert(varchar, invoices.account, 60) 
              FROM invoices
              FOR XML PATH (''))
             , 1, 1, '')
FROM invoices
GROUP BY invoices.invoice, invoices.summ

这是我得到的结果:

invoice summ accounts
ty20210110 200 1001,1002,1003,1004
ty20210110 240 1001,1002,1003,1004
ty20210110 250 1001,1002,1003,1004
ty20210110 300 1001,1002,1003,1004
ty20210110 400 1001,1002,1003,1004
ty20210114 300 1001,1002,1003,1004
ty20210114 400 1001,1002,1003,1004
ty20210114 500 1001,1002,1003,1004

这是我需要得到的结果:

invoice summ accounts
ty20210110 1390 1001,1002
ty20210114 1200 1003,1004

所以实际上我需要获取 2 张不同发票的总和,并用逗号指定与这些发票相关的帐户。

这里的 dbfiddle 也有这些东西:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=7a5de9e680693b5e70ea68cecebef6cc

提前谢谢你们。

【问题讨论】:

  • 您的 SQL Server 版本是多少?

标签: sql-server concatenation for-xml-path stuff


【解决方案1】:

如果您想求和,请不要按summ 分组。在上面使用sum()。并关联子查询。否则,您将获得所有帐户。

SELECT i1.invoice,
       sum(i1.summ) summ,
       stuff((SELECT DISTINCT
                     concat(',', i2.account)
                     FROM invoices i2
                     WHERE i2.invoice = i1.invoice
                     FOR XML PATH ('')),
             1,
             1,
             '') accounts
       FROM invoices i1
       GROUP BY i1.invoice;

【讨论】:

  • FOR XML PATH(''), TYPE)).value('text()[1]','nvarchar(max)'), 1... 最好
【解决方案2】:

对于 SQL Server 2017 及更高版本。

利用STRING_AGG() 函数。唯一的细微差别是我们需要在子查询中选择DISTINCT account 值。

SQL

-- DDL and sample data population, start
DECLARE @invoices TABLE 
(
    invoice VARCHAR(20) NOT NULL,
    quantity INT NOT NULL,
    price INT NOT NULL,
    summ INT NOT NULL, 
    account INT NOT NULL
);
INSERT @invoices(invoice, quantity, price, summ, account) VALUES 
('ty20210110', 2, 100, 200, 1001),
('ty20210110', 3, 100, 300, 1002),
('ty20210110', 1, 250, 250, 1001),
('ty20210110', 2, 120, 240, 1002),
('ty20210110', 4, 100, 400, 1002),
('ty20210114', 3, 100, 300, 1001),
('ty20210114', 5, 80, 400, 1003),
('ty20210114', 5, 100, 500, 1004);
-- DDL and sample data population, end

SELECT i1.invoice
    , SUM(i1.summ) AS summ
    , (
       SELECT STRING_AGG(account,',') FROM 
       (
        (SELECT DISTINCT account FROM @invoices AS i2 WHERE i2.invoice = i1.invoice)
       ) AS x) AS accounts
FROM @invoices AS i1
GROUP BY i1.invoice;

输出

+------------+------+----------------+
|  invoice   | summ |    accounts    |
+------------+------+----------------+
| ty20210110 | 1390 |      1001,1002 |
| ty20210114 | 1200 | 1001,1003,1004 |
+------------+------+----------------+

【讨论】:

  • 您好,看起来没问题,但是如果我有来自另一个表的帐户查询呢?
  • @user421875,很高兴听到建议的解决方案对您有用。请不要忘记将其标记为答案。
  • @user421875,在提出问题时,您需要提供一个可重现的最小示例。你通过 dbfiddle 做到了,我跟着它。请提出另一个问题以涵盖 "...但是如果我有来自另一个表的帐户查询怎么办?..."
  • 抱歉,稍后再做 - 今天要做很多工作。感谢回复
  • 我从我的工作仪表板创建了最接近原始查询的查询。在这里:dbfiddle.uk/… 如果你看这里的截图prntscr.com/zvpqle你会发现由于不同的帐户而重复的行。所以我想连接它们并将相同发票的帐户放在同一行,用逗号分隔。我认为“Stuff and 'For Xml Path'”会对我有所帮助,因为我在另一个仪表板查询中看到过它,但我不明白如何正确设置它。你能帮忙解决这个问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-16
  • 2021-09-02
  • 2015-09-21
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 1970-01-01
相关资源
最近更新 更多