SQL查询将第一行与其余行分开

时间:2015-01-29 11:42:07

标签: sql sql-server-2012

一段时间以来一直在苦苦挣扎,我基本上在数据库中有一个给定id的名字列表,我想在一列中选择id的第一个名称,并为id的其余名称选择进入逗号分隔的其他列。第二列的查询如下:

SELECT KittyName as KittyName, rowNo = ROW_NUMBER() OVER (Order By (select 1) ASC) FROM 
           (SELECT
                (
                    SELECT KittyName + ','
                    FROM KittyNameTable
                    where KittyNameTable.Id = OtherKittyData.Id
                    FOR XML PATH('')
                ) as CombinedKittyNames
           ) as t2 WHERE rowNum > 1

此查询运行而没有rowNum子句生成两列:

KittyName   rowNum
Fluffy       1
Jeff         1
Jeff         2
Marcus       1

但是当我加入它时,它说rowNum不是一列。

我尝试了一些但没有运气。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

尝试

select KittyName, RowNum
from
    (SELECT KittyName as KittyName, rowNum
           (SELECT
                (
                    SELECT KittyName + ','
                    FROM KittyNameTable
                    where KittyNameTable.Id = OtherKittyData.Id
                    FOR XML PATH('')
                ) as CombinedKittyNames
           ) as t2 ) as x
 Where RowNum = 1

答案 1 :(得分:0)

您不能在select子句中使用where中定义的别名。改为使用CTE或子查询:

WITH cte as (
      SELECT KittyName as KittyName,
             rowNum = ROW_NUMBER() OVER (Order By (select 1) ASC) 
      FROM (SELECT
                (
                    SELECT KittyName + ','
                    FROM KittyNameTable
                    where KittyNameTable.Id = OtherKittyData.Id
                    FOR XML PATH('')
                ) as CombinedKittyNames
            FROM OtherKittyData
           ) as t2
     )
SELECT *
FROM CTE
WHERE rowNum > 1;

作为备注:您可能不希望在列表末尾添加逗号。此外,将XML从XML类型转换为字符串更安全,因此诸如&符号的字符不会转换为'&。此查询看起来像:

WITH cte as (
      SELECT ROW_NUMBER() OVER (Order By (select NULL)) as rowNum,
             STUFF((SELECT ',' + KittyName
                    FROM KittyNameTable
                    WHERE KittyNameTable.Id = OtherKittyData.Id
                    FOR XML PATH('concat'), TYPE
                   ).VALUE('/concat[1]', 'varchar(max)'),
                   1, 1, '') as CombinedKittyNames
      FROM OtherKittyData
     )
SELECT *
FROM CTE
WHERE rowNum > 1;

编辑:

如果您想要除第一个之外的所有Kitty名称,那么您将row_number()放在错误的位置。提示:在提问时,请包含样本数据和所需结果。

      SELECT okd.*,
             STUFF((SELECT ',' + KittyName
                    FROM (SELECT knt.*,
                                 ROW_NUMBER() OVER (Order By (select NULL)) as rowNum
                          FROM KittyNameTable knt
                         ) knt
                    WHERE knt.Id = okd.Id AND
                          rowNum > 1
                    FOR XML PATH('concat'), TYPE
                   ).VALUE('/concat[1]', 'varchar(max)'),
                   1, 1, '') as CombinedKittyNames
      FROM OtherKittyData okd;

换句话说,你必须在里面过滤子查询。

顺便说一句,在这种情况下,你不应该使用order by和常量。没有"第一"行。您应该使用显式排序列(例如id)。