按嵌套选择排序

时间:2014-03-08 15:23:11

标签: sql sql-server sql-order-by

我正在使用以下SELECT从数据库中获取数据。

有没有办法按嵌套选择中的项目排序结果? 我尝试ORDER BY B.ID,但这会产生错误。

我的存储过程:

SELECT      (
                SELECT      B.ID,
                            B.FirstName,
                            B.LastName
                FROM        Users B
                WHERE       B.UserNum = A.UserNum
                FOR XML     PATH(''), ELEMENTS, TYPE
            )
FROM        User_SolutionRole A
WHERE       A.Solution = 'SPR'
FOR XML PATH('users'), ELEMENTS, TYPE, ROOT('ranks')

1 个答案:

答案 0 :(得分:4)

如果我们可以将values() method应用于SELECT的唯一列以从中提取ID值,我们可以使用结果对行进行排序,如下所示:

<column_ref>.values('ID[1]', 'int') ASC

实际上可以实现这一目标。如果您为该列指定了名称users,同时将PATH('users')替换为PATH(''),如下所示:

SELECT      (
                SELECT      B.ID,
                            B.FirstName,
                            B.LastName
                FROM        Users B
                WHERE       B.UserNum = A.UserNum
                FOR XML     PATH(''), ELEMENTS, TYPE
            ) AS users
FROM        User_SolutionRole A
WHERE       A.Solution = 'SPR'
FOR XML     PATH(''), ELEMENTS, TYPE, ROOT('ranks')
;

你会获得相同的输出,但该列现在将有一个参考。那将是你迈向目标的第一步。

看起来你只需要像这样添加一个ORDER BY:

SELECT      (
                SELECT      B.ID,
                            B.FirstName,
                            B.LastName
                FROM        Users B
                WHERE       B.UserNum = A.UserNum
                FOR XML     PATH(''), ELEMENTS, TYPE
            ) AS users
FROM        User_SolutionRole A
WHERE       A.Solution = 'SPR'
ORDER BY    users.value('ID[1]', 'int') ASC
FOR XML     PATH(''), ELEMENTS, TYPE, ROOT('ranks')
;

然而,这不起作用,因为在SELECT子句中分配的别名只能由与相同的ORDER BY子句引用,即它不能是一个表达。所以上面会导致编译错误。

解决方法是将名称​​ previous 分配给主SELECT。基本上有两种方式:

  1. 使用派生表:

    SELECT      users
    FROM        (
                    SELECT      (
                                    SELECT      B.ID,
                                                B.FirstName,
                                                B.LastName
                                    FROM        Users B
                                    WHERE       B.UserNum = A.UserNum
                                    FOR XML     PATH(''), ELEMENTS, TYPE
                                ) AS users
                    FROM        User_SolutionRole A
                    WHERE       A.Solution = 'SPR'
                ) AS s
    ORDER BY    users.value('ID[1]', 'int') ASC
    FOR XML     PATH(''), ELEMENTS, TYPE, ROOT('ranks')
    ;

    以上使用“普通”子选择,但如果您将其声明为CTE则没有区别。

  2. 使用CROSS APPLY

    SELECT      x.users
    FROM        User_SolutionRole A
    CROSS APPLY (
                    SELECT      B.ID,
                                B.FirstName,
                                B.LastName
                    FROM        Users B
                    WHERE       B.UserNum = A.UserNum
                    FOR XML     PATH(''), ELEMENTS, TYPE
                ) AS x (users)
    WHERE       A.Solution = 'SPR'
    ORDER BY    x.users.value('ID[1]', 'int') ASC
    FOR XML     PATH(''), ELEMENTS, TYPE, ROOT('ranks')
    ;
  3. 我个人的偏好是CROSS APPLY technique看起来更简单,(对我来说)更清晰,但former method同样有效。