【问题标题】:Order by nested select按嵌套选择排序
【发布时间】:2014-03-08 15:23:11
【问题描述】:

我正在使用以下 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')

【问题讨论】:

  • ORDER BY 该列的编号ORDER BY 1
  • 谢谢,我在尝试此操作时遇到错误:消息 305,级别 16,状态 1,过程 FetchUsersAll,第 23 行 XML 数据类型无法比较或排序,除非使用 IS NULL 运算符。
  • 试试ORDER BY CAST(B.ID AS NVARCHAR(100))
  • 否:消息 4104,级别 16,状态 1,过程 FetchUsersAll,第 23 行无法绑定多部分标识符“B.ID”。
  • 然后我得到:Msg 207,Level 16,State 1,Procedure FetchUsersAll,Line 23 Invalid column name 'ID'。

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


【解决方案1】:

如果我们可以将 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 子句按原样引用,即它不能是一部分的一种表达方式。所以上面会导致编译错误。

解决方案是将名称 prior 分配给主 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')
    ;

我个人的偏好是CROSS APPLY technique 看起来更简单(对我来说)更清晰,但former method 也同样适用。

【讨论】:

  • 这实际上非常好 - 我将使用交叉申请。非常感谢您的详细回复!
猜你喜欢
  • 1970-01-01
  • 2018-07-14
  • 2016-01-07
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多