单选加入Sql查询

时间:2013-04-24 08:59:49

标签: sql sql-server tsql join

TableA与下面提供的数据一起使用,我需要一个SELECT查询,该结果会在TableB中返回结果:

表A

Id  Cvs 
--------------------------------
1   aaa,eee,ccc,ggg,hhh,bbb
2   ggg,bbb,ccc,ggg,aaa,bbb,bbb
3   ddd,ggg,eee

表B

Id  Value
1   aaa
1   eee
1   ccc
1   ggg
1   hhh
1   bbb
2   ggg
2   bbb
2   ccc
2   ggg
2   aaa
2   bbb
2   bbb
3   ddd
3   ggg
3   eee

由于T-SQL函数或连接查询,请帮助我如何操作。

4 个答案:

答案 0 :(得分:0)

请尝试:

DECLARE @table as TABLE(ID int, CVS  Nvarchar(50))
insert into @table
select 1, 'aaa,eee,ccc,ggg,hhh,bbb' CVS union all
select 2, 'ggg,bbb,ccc,ggg,aaa,bbb,bbb' CVS union all
select 3, 'ddd,ggg,eee'

;WITH Split_Col 
AS
(
    SELECT ID, CONVERT(XML,'<table><col>' + ColName + '</col></table>') AS xmlcol
    FROM
    (
        SELECT ID, Split.a.value('.', 'VARCHAR(100)') AS ColName  
        FROM  
        (
             SELECT ID, CAST ('<M>' + REPLACE(CVS, ',', '</M><M>') + '</M>' AS XML) AS ColName  
             FROM  (select * from @table) TableName
         ) AS A 
            CROSS APPLY ColName.nodes ('/M') AS Split(a)
    ) TableName
)

 SELECT      
 ID, xmlcol.value('/table[1]/col[1]','varchar(100)') AS studentID
 FROM Split_Col 
 order by ID

答案 1 :(得分:0)

试试这个

SELECT A.ID,  
     Split.a.value('.', 'VARCHAR(100)') AS CVS  
FROM  
(
    SELECT ID,  
         CAST ('<M>' + REPLACE(CVS, ',', '</M><M>') + '</M>' AS XML) AS CVS  
    FROM  TableA 
) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a)

答案 2 :(得分:0)

我会创建一个单独的函数,从CSV列表中返回所有值(包括重复的值):

IF  EXISTS (SELECT * FROM sysobjects WHERE id  = OBJECT_ID(N'[dbo].[fn_TEST]') AND xtype  IN (N'FN', N'IF', N'TF'))
BEGIN
    DROP FUNCTION [dbo].[fn_TEST]
END
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[fn_TEST]
(
    @CSVList NVARCHAR(MAX)
)
RETURNS @ResultSet TABLE
(
     RecValue NVARCHAR(MAX)
    ,RecID BIGINT IDENTITY(1, 1) PRIMARY KEY
)
AS
BEGIN

    DECLARE @XML xml = N'<r><![CDATA[' + REPLACE(@CSVList, ',', ']]></r><r><![CDATA[') + ']]></r>'

    INSERT INTO @ResultSet (RecValue)
    SELECT RTRIM(LTRIM(Tbl.Col.value('.', 'nvarchar(max)')))
    FROM @xml.nodes('//r') Tbl(Col)

    RETURN
END

GO

然后您可以简单地使用“SELECT”语句和“CROSS APPLY”语句,如下所示:

SET NOCOUNT ON
GO

    DECLARE @DataSource AS TABLE
    (
         ID TINYINT IDENTITY(1,1)
        ,CSV NVARCHAR(4000)
    )

    INSERT INTO @DataSource ([CSV])
    VALUES ('aaa,eee,ccc,ggg,hhh,bbb')
          ,('ggg,bbb,ccc,ggg,aaa,bbb,bbb')
          ,('ddd,ggg,eee')

    SELECT ID
          ,RecValue
    FROM @DataSource DS
    CROSS APPLY [dbo].[fn_TEST](CSV) FN

SET NOCOUNT OFF
GO

答案 3 :(得分:0)

请尝试其中一项 -

DECLARE @temp TABLE
(
      id INT
    , string NVARCHAR(200)
)

DECLARE @Separator CHAR(1)
SELECT @Separator = ','

INSERT INTO @temp (id, string)
VALUES 
(1,   'aaa,eee,ccc,ggg,hhh,bbb'),
(2,   'ggg,bbb,ccc,ggg,aaa,bbb,bbb'),
(3,   'ddd,ggg,eee')

<强> 1。 XML

SELECT 
      id = p.value('(./n)[1]', 'INT')
    , name = p.value('(./s)[1]', 'NVARCHAR(200)')
FROM (
    SELECT field = CAST('<r><s>' + REPLACE(SUBSTRING(',' + t.string + ',', 2, LEN(',' + t.string + ',')), @Separator, '</s><n>' + CAST(t.id AS VARCHAR(10)) + '</n></r><r><s>') + '</s></r>' AS XML) 
    FROM @temp t
) d
CROSS APPLY field.nodes('/r') t(p)
WHERE t.p.exist('n') = 1

<强> 2。 spt_values

SELECT 
      t.id
    , name = 
        SUBSTRING(
              ',' + t.string + ','
            , number + 1
            , CHARINDEX(@Separator, ',' + t.string + ',', number + 1) - number - 1)
FROM @temp t
CROSS JOIN [master].dbo.spt_values n
WHERE [type] = 'p'
    AND number <= LEN(',' + t.string + ',') - 1
    AND SUBSTRING(',' + t.string + ',', number, 1) = @Separator

第3。 WHILE

DECLARE @items TABLE 
(
      id INT
    , name NVARCHAR(50)
)

DECLARE
      @id INT
    , @string NVARCHAR(2000)
    , @pos INT

DECLARE cur CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
    SELECT id, string
    FROM @temp

OPEN cur

FETCH NEXT FROM cur INTO @id, @string

WHILE @@FETCH_STATUS = 0 BEGIN

    WHILE LEN(@string) > 0 BEGIN

        SELECT @pos = CHARINDEX(@Separator, @string, 1)

        IF @pos = 0
            SELECT @pos = LEN(@string)

        INSERT INTO @items (id, name) 
        SELECT @id, SUBSTRING(@string, 1, @pos - 1)

        SELECT @string = SUBSTRING(@string, @pos + 1, LEN(@string) - @pos)

    END

    FETCH NEXT FROM cur INTO @id, @string

END

CLOSE cur
DEALLOCATE cur

SELECT  
      i.id
    , i.name 
FROM @items i
WHERE name != ''

<强> 4。 CTE

;WITH a AS
(
    SELECT 
          id
        , start_pos = 1
        , end_pos = CHARINDEX(@Separator, t.string)
        , t.string
    FROM @temp t

    UNION ALL

    SELECT 
          id
        , end_pos + 1
        , CHARINDEX(@Separator, string, end_pos + 1)
        , string
    FROM a
    WHERE end_pos > 0
)

SELECT 
      d.id
    , d.name 
FROM (
    SELECT 
          a.id
        , name = SUBSTRING(
              string
            , start_pos
            , ABS(end_pos - start_pos)
        ) 
    FROM a
) d
WHERE d.name != ''