【问题标题】:How to concatenate Multiple Rows from Multiple Tables Efficiently如何有效地连接多个表中的多行
【发布时间】:2016-12-02 23:07:49
【问题描述】:

我有多个表,其中一个外键来自一个主表。表格是这样的:

姐妹

MainID    IDNO   ....
111111       1   ....          
111111       1   ....          
111111       1   ....
222222       1   ....          
111111       2   ....          

兄弟们

MainID    IDNO   ....
111111     555   ....          
111111     333   ....          
111111     111   ....
222222     222   ....          
111111     321   ....          

叔叔

MainID    IDNO   ....
111111     561   ....          
111111     121   ....          
111111     331   ....
222222     451   ....          
111111     672   .... 

我需要将所有IDNos 连接起来,但我似乎无法获得所有信息,例如我可能无法获得 672

SELECT 
    ',' + S1.IDNo + ',' + B1.IDNo + ',' + U1.IDNo AS [text()] 
FROM 
    Sisters S1, Brothers B1, Uncles U1, MainTable 
WHERE 
    D1.MainID = MainTable.ID 
    AND S1.MainID = MainTable.ID 
    AND B1.MainID = MainTable.ID 
FOR XML PATH('')

我尝试分隔表并稍后合并,但这样会变得慢得多。我能做什么?

预期输出:

,1,1,1,1,2,555,333,111,222,321,561,121,331,451,672

【问题讨论】:

  • 仅供参考:主表有大约 200.000 条记录,子表有大约 600.000 条记录。
  • Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 ANSI 中的 proper ANSI JOIN 语法-92 SQL 标准(20 多年前),不鼓励使用它
  • @marc_s 我也用过join,速度影响不大
  • 想必你想要union all,但没有样本结果,那只是推测。
  • 这与速度无关,而是关于可读性,因此可维护性,并避免意外的交叉连接(笛卡尔积)....

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


【解决方案1】:

根据预期的输出,看起来 3 个表中的每一个中的 MainID 列在输出中都没有发言权(如果是这样)那么这应该对你有用,尽管我不确定它是否会扩展处理 600K+ 记录。出于好奇,您为什么要连接如此大的值列表?

Declare @x as varchar(max) = ''

SELECT @x = @x + ',' + CAST(A.IDNO as varchar)  FROM
(
select 1 as IDNO UNION ALL
select 2 as IDNO UNION ALL
select 3 as IDNO UNION ALL
select 4 as IDNO 
) A -- Pretend this is your Sisters tables
FOR XML PATH('')
PRINT @X -- Just for Debugging Purposes

SELECT @x = @x + ',' + CAST(B.ID as varchar)  FROM
(
select 55 as IDNO UNION ALL
select 66 as IDNO UNION ALL
select 77 as IDNO UNION ALL
select 88 as IDNO 
) B -- Pretend this is your Brothers tables

PRINT @X -- Just for Debugging Purposes

SELECT @x = @x + ',' + CAST(C.IDNO as varchar)  FROM
(
select 555 as IDNO UNION ALL
select 666 as IDNO UNION ALL
select 777 as IDNO UNION ALL
select 888 as IDNO 
) C -- Pretend this is your Uncles tables


PRINT @X -- Final Output 
SELECT @X as XML_Output FOR XML PATH('') 

输出:

,1,2,3,4
,1,2,3,4,55,66,77,88 
,1,2,3,4,55,66,77,88,555,666,777,888 -- Final Result

<XML>,1,2,3,4,55,66,77,88,555,666,777,888</XML> -- XML Output

所以在你的情况下你可以做这样的事情(再次不确定它在大桌子上的表现如何)

Declare @x as varchar(max) = ''
SELECT  @x = @x + ',' + CAST(A.IDNO as varchar)  FROM
(
select MainID ,   IDNO FROM SISTERS  UNION ALL
select MainID ,   IDNO FROM BROTHERS UNION ALL
select MainID ,   IDNO FROM UNCLES
) A


SELECT @X as XML_Output FOR XML PATH('') 

【讨论】:

  • 好吧,我想要这个列表,因为客户想从子表中搜索带有 idno 的主要项目。虽然不知道有没有别的办法,但我想到的最合理的就是这个了。例子;如果客户在 ID 中搜索 555,考虑到我的问题,我应该显示 ID 为 111111 的主要项目。
猜你喜欢
  • 2021-02-05
  • 1970-01-01
  • 2013-11-30
  • 2021-02-04
  • 2019-02-08
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
  • 2013-01-22
相关资源
最近更新 更多