选择查询

时间:2017-02-09 15:52:34

标签: sql sql-server greatest-n-per-group nested-sets

我试图编写一个使用Nested Interval Hierarchy数据库模型的SQL查询。

--Given a parent Id, this query retrieves the position of the youngest child which can be inserted into the table
SELECT TOP 1
    --compute values based on the youngest "sibling id" (the one with the highest value)
    (parent.m_11 * (FLOOR(child.m_11/child.m_12)+2) - parent.m_12) as m_11,
    (parent.m_11) as m_12, 
    (parent.m_21 * (FLOOR(child.m_11/child.m_12)+2) - parent.m_22) as m_21,
    (parent.m_21) as m_22
    FROM my_so_table child
        --grabs all children of the parent
        JOIN my_so_table parent
          ON parent.Id = 1
         AND parent.m_21 = child.m_22
         AND parent.m_11 = child.m_12
    --the operation "Floor(child.m_11 / child.m_12) is the siblingId that I need to do math on above
    ORDER By FLOOR(child.m_11/child.m_12) DESC
GO

使用架构:

GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[my_so_table](
    [m_11] [int] NOT NULL,
    [m_12] [int] NOT NULL,
    [m_21] [int] NOT NULL,
    [m_22] [int] NOT NULL,
    [Id] [int] IDENTITY(1,1) NOT NULL)
GO

INSERT INTO [dbo].[my_so_table] VALUES (2,1,1,0); --1.
INSERT INTO [dbo].[my_so_table] VALUES (3,1,1,0); --2.
INSERT INTO [dbo].[my_so_table] VALUES (3,2,2,1); --1.1
INSERT INTO [dbo].[my_so_table] VALUES (4,1,1,0); --3.

使用上述架构,运行父{1}}的上述查询正确返回

1

正确表示要在Id为1的父项下插入的新节点的矩阵。在5,2,3,1 的parentId上运行上述查询将返回一个空列表,当它应该返回时

2

表示Id为2的父母下的第一个孩子的矩阵。

这是错误的,因为我的查询没有处理没有父级子节点的情况。如果没有父级的子级,则5,3,2,1 的结果应为-1。如何更改查询以完成此操作?

1 个答案:

答案 0 :(得分:1)

我找到了解决方案。我在回避greatest-n-by-group,实际上我不明白group-by是如何运作的。

--Given a parent Id, this query retrieves the position of the youngest child which can be inserted into the table
--insert into my_so_table(m_11, m_12, m_21, m_22)
SELECT TOP 1
    --compute values based on the youngest 'sibling id' (the one with the highest value)
    (parent.m_11 * (ISNULL(siblingId, 0) + 2) - parent.m_12) as m_11,
    (parent.m_11) as m_12, 
    (parent.m_21 * (ISNULL(siblingId, 0) + 2) - parent.m_22) as m_21,
    (parent.m_21) as m_22
    FROM my_so_table parent
        --grabs all children of the parent
        LEFT JOIN (
            --Grabs the youngest sibling for each sibling chain
            SELECT
                child.m_12,
                child.m_22,
                Max(Floor(child.m_11 / child.m_12)) as siblingId
            FROM my_so_table child
            Group By child.m_12, child.m_22
        ) child
        on(parent.m_21 = child.m_22)
        AND(parent.m_11 = child.m_12)
    WHERE parent.Id = @parentId
    ORDER By siblingId DESC
GO

group-by之前没有工作,因为我无法从子查询中检索m_12m_22,因为我没有group by这两个值。切换到left-join会导致报告空值,这正是我需要的!