【问题标题】:SQL Server: CTE tree with prioritySQL Server:具有优先级的 CTE 树
【发布时间】:2016-03-04 22:33:42
【问题描述】:

我在如何在 SQL Server 中为递归父子树构建查询时遇到了一些麻烦。

我找到了一些常见的表表达式,但我必须考虑另一个我在互联网上搜索没有找到的参数(每个级别的优先级),所以我的表结构是这样的

id - parentid - proprity

例如,如果我有这个数据:

1 - NULL - 2
2 - NULL - 1
3 - 2 - 2
4 - 3 - 1
5 - 2 - 0
6 - 1 - 0
7 - 2 - 3

查询必须以正确的顺序返回:

-2
--5
--3
---4
--7
-1
--6

此外,此列表是可订购的,因此如果有任何订单更改,我必须在正确的位置重置优先级。任何人都已经通过 SQL Server 中的查询来解决这种情况?

提前致谢

【问题讨论】:

标签: sql sql-server common-table-expression


【解决方案1】:

这将为您提供所需的订单。就个人而言,我会尝试在显示层中进行排序,但这将在 SQL 中进行。

这依赖于一位数的优先级值。如果这些可能更大,那么您需要在优先级前面加上前导 0,例如:RIGHT('0' + priority, 2)

查询只是在每个点构建一个优先级字符串,以便您可以对其进行排序。

;WITH Hierarchy_CTE AS
(
    SELECT
        id,
        parent_id,
        CAST([priority] AS VARCHAR(100)) AS priority_string,
        id AS base,
        1 AS lvl
    FROM
        My_Table
    WHERE
        parent_id IS NULL
    UNION ALL
    SELECT
        MT.id,
        MT.parent_id,
        CAST(H.priority_string + CAST(MT.priority AS VARCHAR(20)) AS VARCHAR(100)),
        H.base,
        H.lvl + 1
    FROM
        Hierarchy_CTE H
    INNER JOIN My_Table MT ON MT.parent_id = H.id
)
SELECT
    id,
    base,
    lvl
FROM
    Hierarchy_CTE
ORDER BY
    priority_string

【讨论】:

  • 感谢您的回复,我已经尝试过您的查询,但如果您有超过 10 个项目,它就无法正常工作,因为第十个“相对”位置之后的第一级项目高于他们必须.
  • 我刚刚运行了包含 11 个项目的查询,它返回的结果完全符合预期。你的意思是优先级大于10?正如我在回答中解释的那样,如果是这种情况,您必须更改代码。如果您仍然遇到问题,请在您的问题中添加额外的示例数据和预期输出,这会导致此操作失败,我会看看它。
  • 我已经尝试了至少四个随机优先级的级别...一个解决方案可以添加具有总固定长度的填充零...我会尽快尝试这个解决方案,我注意到你的结果
【解决方案2】:

看来这个解决方案是有效的(取自 Tom H 的回答):

;WITH Hierarchy_CTE AS
(
    SELECT
        id,
        parent_id,
        CAST(REPLICATE('0', 10 - LEN(CAST([Order] AS VARCHAR))) + CAST([Order] AS VARCHAR) + '.' + 
    REPLICATE('0', 10 - LEN(CAST(MerchantCategoryId AS VARCHAR))) + CAST(MerchantCategoryId AS VARCHAR) AS VARCHAR(4000)) AS priority_string,
        id AS base,
        1 AS lvl
    FROM
        My_Table
    WHERE
        parent_id IS NULL
    UNION ALL
    SELECT
        MT.id,
        MT.parent_id,
        CAST(H.priority_string + '|' + REPLICATE('0', 10 - LEN(CAST(MT.[priority] AS VARCHAR))) + CAST(MT.[priority] AS VARCHAR) + '.' + 
    REPLICATE('0', 10 - LEN(CAST(MT.id AS VARCHAR))) + CAST(MT.id AS VARCHAR) AS VARCHAR(4000)) AS priority_string,
        H.base,
        H.lvl + 1
    FROM
        Hierarchy_CTE H
    INNER JOIN My_Table MT ON MT.parent_id = H.id
)
SELECT
    id,
    base,
    lvl
FROM
    Hierarchy_CTE
ORDER BY
    priority_string

我添加了等于固定长度减去“字符串化”优先级长度以及 id 的填充零,因此我可以将它们排序为优先级,然后排序为 id。 此解决方案仅适用于升序(不适用于维护树视图的降序),但此列表仅在我必须保存更新的优先级时对我有用,因此可能就足够了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 2011-03-19
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多