选择查询中的 SQL 条件变量

Posted

技术标签:

【中文标题】选择查询中的 SQL 条件变量【英文标题】:SQL conditional variables in select query 【发布时间】:2017-02-09 15:52:34 【问题描述】:

我正在尝试编写一个使用 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 的 parentId 运行上述查询会正确返回

5,2,3,1

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

5,3,2,1

表示id为2的parent下第一个child的矩阵。

这是错误的,因为我的查询没有处理没有父母子女的情况。如果没有父母的孩子,Floor(child.m_11 / child.m_12) 的结果应该是 -1。如何更改我的查询以完成此操作?

【问题讨论】:

什么是“我知道 T-SQL 中有变量,但我正在尝试编写符合 SQL 的代码。”意思是?您是否试图避免变量或以您的代码应该 100% 可移植为幌子的东西?我完全不清楚你想在这里做什么。 “假装你的代码应该是 100% 可移植的”是的。至少,如果可能的话,这就是目标。我是一个非常天真的 SQL 开发人员,所以我不知道 SQL 最佳实践。设定可移植代码的目标似乎是个好主意。 明确地说,如果没有父母的孩子,我需要在选择查询中使用“-1”而不是“Floor(child.m_11/child.m_12)”。我不知道如何做到这一点。 可移植性的讨论远远超出了这里的范围,但老实说,您多久更改一次数据库系统? :) 至于您手头的主题,我们需要查看一些详细信息而不仅仅是查询。这是一个很好的起点。spaghettidba.com/2015/04/24/… 这样更好吗? :) 另外,我不确定如何更好地表达我的问题而不是“如何更改我的查询以完成此操作”。我希望最终能想出一个更好的方法来问这个问题。 【参考方案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 处理这两个值。切换到左连接会导致报告空值,这正是我所需要的!

【讨论】:

以上是关于选择查询中的 SQL 条件变量的主要内容,如果未能解决你的问题,请参考以下文章

C# SQL条件查询语句where中使用变量的用法

将值设置为变量并根据条件SQL进行修改

SQLDeveloper支持绑定变量的IN条件

thinkphp5 怎么将变量作为模糊查询条件

带有 VB.net 变量字符串条件的动态 SQL 查询

如何优化Oracle在where条件中用了自定义函数的SQL语句