【问题标题】:Data result table containing sub tables in TSQL?SQL中包含子表的数据结果表?
【发布时间】:2021-03-25 13:19:21
【问题描述】:

我正在处理一个产品页面,我必须一次查询所有数据,并且其中一列应该包含多个值。在这种特殊情况下,它是包含多张图片的产品列表。不幸的是,我不能压缩同一列中的所有图片以便稍后对其进行切片,因为数据将在 XML.CONFIG 页面中处理,该页面使用 for-each 处理数据。这就是我所拥有的。

简而言之,如果有一种方法可以选择数据,每条记录都有一个“子列表”。

示例...

产品表:

Id  ProdId  Desc
1   9003    Shirt
2   9004    Trouser

图片表:

Id  PicId   ProdId
1   A       9003
2   B       9003
3   C       9004
4   D       9004
5   E       9003

查询结果:

ProdId  Desc    PicId
9003    Shirt   
                A
                B
                E
9004    Trouser 
                C
                D

我知道这听起来很疯狂,但我记得大约 20 年前,我在一个用于教会管理的 VB 程序中使用 SQL Server Express 和 Crystal Reports 做了类似的事情。我们有一份报告列出了会众成员,并将他们的捐款分组在每个成员下面。我确信我所做的一切都是运行一个 SQL 查询来完成这项工作,但这是很久以前的事了,我不记得它是如何完成的。

有什么想法吗?

补充说明:

我只记得在我使用命令“SHAPE”时。我在 T-SQL 文档中找到了一个示例,但不知道为什么它不起作用。我的代码:

SHAPE {SELECT ProdId,Desc FROM product} AS PRO
APPEND ({SELECT PicId FROM pics} AS PIC
RELATE PRO.ProdId TO PIC.ProdId)

这很奇怪。我的做法与示例完全相同,但它说 } 附近有一个 sintax 错误。

T-SQL 文档: https://docs.microsoft.com/mt-mt/sql/ado/guide/data/shape-append-clause?view=sql-server-2017

【问题讨论】:

  • 这是表示层的任务,而不是 RDBMS。
  • “T-SQL 文档:” 这不是 Transact-SQL 文档;这是给 ADO 的。
  • 哎呀,是的,我完全错过了这个! :-( 谢谢,我会尝试另一种方法
  • PS:将其发布为答案,以便我可以接受它已解决。我相信它会为您带来一些价值。 ;-)
  • 我还没有在这里给出答案来发一个,严。

标签: tsql join subset sublist


【解决方案1】:

这是prodid 上的简单左连接。

SELECT pr.prodid,
       pr.desc,
       pi.picid
       FROM product pr
            LEFT JOIN picture pi
                      ON pi.prodid = pr.prodid
       ORDER BY pr.prodid,
                pi.picid;

这会得到你

prodid desc left
9003 Shirt A
9003 Shirt B
9003 Shirt E
9004 Trouser C
9004 Trouser D

其余的是 @Larnu 评论的表示层逻辑。每次遇到尚未处理的产品时,您基本上都会遍历结果并打印产品的标题行。在任何一种情况下都打印图片行。

【讨论】:

  • 我知道如何执行连接,但这不是我所追求的。您的查询生成了 5 条记录,它应该只有 2 条(我认为我的示例在这个意义上非常清楚)。无论如何,我正在尝试 TSQL 文档中的 SHAPE 命令(我记得它是我当时使用的),但由于某种原因它不起作用。
  • @YanKleber:您的示例结果有七行...是的,正如我所写的,从五行到七行的这种转换将由表示层处理。
  • 不,它有两行,每行都有子集。对不起,如果我不能更清楚这一点。也可以使用 SHAPE 命令在 T-SQL 中完成。我只是无法意识到为什么它不起作用。请参阅我在 OP 中附加的说明。
  • @YanKleber:据我所知,SQL Server 中的一行列中不存在子集(Oracle 确实知道嵌套表,但不知道 SQL Server)。因此,您的结果的唯一合乎逻辑的解释是七行,而不是两行。但是好的,我现在明白你的意思了,在这里很难介绍。但我仍然想您想在某个程序中显示该结果,因此获取 possible 关系结果并按照描述对其进行处理是一种方法。
  • 当然,没问题,谢谢。拉努解决了这个问题。再次感谢。
【解决方案2】:

如果您使用的是 SQL 2017,则可以使用 STRING_AGG 函数。如果不是,那么我将使用 FOR XML 子句,例如:

CREATE TABLE #PRODUCT(Id int, ProdId int, [Desc] varchar(50))
INSERT INTO #PRODUCT VALUES
(1,9003,'Shirt'),
(2,9004,'Trouser')

CREATE TABLE #PICTURE(Id int,  PicId varchar(4),   ProdId int)
INSERT INTO #PICTURE VALUES
(1,'A', 9003),
(2,'B', 9003),
(3,'C', 9004),
(4,'D', 9004),
(5,'E', 9003)

对于 SQL 2017 及更高版本:

select p.id,p.ProdId, STRING_AGG(pt.PicID, CHAR(13)) PicID
from #PRODUCT p
INNER JOIN #PICTURE PT on p.ProdId = pt.ProdId 
GROUP BY p.Id,p.ProdId

适用于 SQL 2016 及以下版本:

SELECT p.id,p.ProdId,   
        STUFF(
             (SELECT  CHAR(13) +  pt.PicID 
              FROM #PICTURE pt
              WHERE p.ProdId = pt.ProdId
              FOR XML PATH ('')) 
             , 1, 1, '') PicID
    FROM #PRODUCT p
GROUP BY p.Id,p.ProdId

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2012-01-02
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 2020-07-12
    • 2012-12-02
    相关资源
    最近更新 更多