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

SQL query separating the first row from the rest

为此苦苦挣扎了一段时间,我基本上在数据库中有一个给定 id 的名称列表,我想 select 将 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 不是一列。

我尝试了一些方法但没有成功。有什么想法吗?

尝试

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

您不能在 where 子句的 select 中使用定义的别名。请改用 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 与常量一起使用。没有 "first" 行。您应该使用明确的排序列(例如 id)。