在SQL中拆分列,然后在另一个表中查找每个列

时间:2011-03-04 14:53:12

标签: c# asp.net sql tsql

我不确定这在SQL中是否可行,如果不是,我会以编程方式进行 - 但如果有办法,它会很棒。

基本上,我在一个表中有一个列,它用另一个表中的ID填充,用逗号分隔 - 所以字段可能如下所示:

3,4,9

这些链接到另一个表,其中上面字段中的数字是行的主键。在行中是一个描述,我想向用户显示而不是数字。

基本上,我不想向用户显示3,4,9,而是想在另一个表中查找相关描述。这可能吗?

4 个答案:

答案 0 :(得分:2)

您可以编写一个表值函数来执行拆分,然后将该结果与查找表结合起来。

答案 1 :(得分:1)

克里斯,

有一种方法可以在T-SQL中执行此操作,实际上非常简单。首先,你需要创建一个像下面这样的函数...(使用基于零的“Tally”cte的全新方法,它很快,因为它不会连接任何分隔符)。

 CREATE FUNCTION dbo.DelimitedSplit8KNEW
--===== Created by Jeff Moden (Prototype: Testing Still in Progress)
--===== Define I/O parameters
        (
        @pString    VARCHAR(8000),
        @pDelimiter CHAR(1)
        )
RETURNS TABLE
   WITH SCHEMABINDING
     AS
 RETURN
WITH 
      E1(N) AS (
                SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
               ),                          --10
      E2(N) AS (SELECT 1 FROM E1 a, E1 b), --100
      E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10,000
cteTally(N) AS (
                SELECT 0 UNION ALL
                SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E4
               )
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY t.N),
        ItemValue  = SUBSTRING(@pString,t.N+1,ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,t.N+1),0),DATALENGTH(@pString)+1)-t.N-1)
   FROM cteTally t
  WHERE t.N BETWEEN 0 AND DATALENGTH(@pString)
    AND (SUBSTRING(@pString,t.N,1) = @pDelimiter OR t.N = 0)
;
GO

现在,看看它是如何使用的......让我们假设你有一个带有唯一列的表和你的CSV列如下(这也构建了数据)。我们所要做的就是用函数交叉应用原始数据,并且数据被神奇地拆分,准备与另一个表连接:

--===== This just builds some test data 
     -- and is not a part of the solution
 SELECT *
   INTO #TestTable
   FROM (
         SELECT 1,'3,4,9'   UNION ALL
         SELECT 2,'3,2,100' UNION ALL
         SELECT 3,'14,35,8,21,27,12'
        ) d (RowNum,CsvValue)
;
--===== Split the data out giving the unique RowNum
     -- from the original data, the element position,
     -- the the value of the split element.  You can
     -- join this SELECT with a table to get the other
     -- values.
 SELECT data.RowNum, split.ItemNumber, split.ItemValue
   FROM #TestTable data
  CROSS APPLY dbo.DelimitedSplit8KNEW(data.CsvValue,',') split
;

这是输出......

RowNum      ItemNumber           ItemValue
----------- -------------------- ---------
1           1                    3
1           2                    4
1           3                    9
2           1                    3
2           2                    2
2           3                    100
3           1                    14
3           2                    35
3           3                    8
3           4                    21
3           5                    27
3           6                    12

(12 row(s) affected)

答案 2 :(得分:0)

你可能想看看这个:

http://www.sommarskog.se/arrays-in-sql.html

并使用它来执行带有IN子句的子查询。

答案 3 :(得分:0)

您是否有兴趣更改架构?通常,在单个字段中存储多个数据是一种可怕的做法。一对多关系似乎更合适。