【问题标题】:TSQL: Join columns, but rows in one column have multiple valuesSQL:连接列,但一列中的行有多个值
【发布时间】:2013-07-17 13:57:15
【问题描述】:

我有一个查询,我必须加入两个表。让我们说T1和T2。 T1 有一个带有 Id 的列。每一行只有一个 Id 值。但是,第二张桌子是我苦苦挣扎的地方。在 T2 中有一列带有 Id,但一行可能有多个 Id。 例如,T1.col1 有这个值:737382。但是 T2.col2 可以在一行中有这个条目:737382;239112;2838210;9923834;2388342;...

我知道这种结构违反了 1NF 之类的。但我无法更改数据或数据结构中的任何内容。 现在我想做的是加入这两个表。请让我知道我是否缺少告诉任何相关信息以回答我的问题。来晚了,我的大脑已经筋疲力尽了~.~

【问题讨论】:

    标签: sql-server-2008 tsql join rows


    【解决方案1】:

    试试

        select tab2.*   -- whatever
          from t1 tab1
    inner join t2 tab2 on ( ';'||tab2.col2||';' like '%;'||tab1.col1||';%' )
             ;
    

    附加的; 字符用于避免连接条件中的分离。

    【讨论】:

    • 感谢您的回复。这似乎很简单,所以我决定尝试一下。但是我使用 MSSQL Server 2008,它不适用于 ||操作员。我什至不知道这是什么意思。你能告诉我它是什么意思,所以我可以将你的帖子标记为答案吗? (只要它会起作用)最好的问候
    • || 运算符等效于 concat 调用。
    • 谢谢,我现在已经自己想通了。可惜我没有早点明白:/
    • 是的,你的答案很完美......只是需要时间来执行。 :)
    【解决方案2】:

    您可以在联接中使用正则表达式,您的正则表达式可以在T2.col2 中检查您的T1.col1。正则表达式应该检查字符串开头的值(即T2.col2)或前面是';',后面总是';'

    【讨论】:

      【解决方案3】:

      您是否尝试过类似的方法:

      select 
          a.column1, 
          a.column2, 
          b.column1,
          b.column2 
      from table a 
      inner join table b on a.column1 = b.column1
      

      【讨论】:

        【解决方案4】:

        由于一个 T2.Col2 可以保存 n 个条目,因此您需要使用表值函数将它们解析为行,然后使用 CROSS APPLY

        注意,如果 T2 很大,此解决方案将挂起很长时间

        类似这样的:

        ;WITH IDSplitted AS 
        (
           SELECT * 
           FROM  T2
           CROSS APPLY dbo.[StringSplit](col2, ';')
        )
        
        SELECT * -- or whatever columns you need
        FROM T1
        INNER JOIN IDSplitted  ON IDSplitted.val = t1.col1
        

        有StringSplit:

        CREATE FUNCTION [dbo].[StringSplit]
        (
          @delimited nvarchar(max),
          @delimiter nvarchar(100)     
        ) RETURNS @t TABLE
        (
        -- Id column can be commented out, not required for sql splitting string
          id int identity(1,1), -- I use this column for numbering splitted parts
          val nvarchar(max)
        )
        AS
        BEGIN
          declare @xml xml
          set @xml = N'<root><r>' + replace(@delimited,@delimiter,'</r><r>') + '</r></root>'
        
          insert into @t(val)
          select 
            r.value('.','varchar(max)') as item
          from @xml.nodes('//root/r') as records(r)
        
          RETURN
        END
        

        【讨论】:

        • 感谢您的回答!我一放假回来就去看看,可以试试看!
        【解决方案5】:

        使用 collapstar 的解决方案后(这是正确的),我遇到了性能问题。所以我所做的是创建一个映射表,这样当我必须再次运行查询时,我不必等待那么久。所以我有一个预定的工作,它会在晚上进行连接并将输出写入映射表

        【讨论】:

          猜你喜欢
          • 2013-05-11
          • 1970-01-01
          • 1970-01-01
          • 2021-05-30
          • 1970-01-01
          • 2010-11-12
          • 1970-01-01
          • 1970-01-01
          • 2018-08-27
          相关资源
          最近更新 更多