Sql &引用;“条件条件”;在WHERE子句中(应用哪种条件取决于“模式”标志)

Sql &引用;“条件条件”;在WHERE子句中(应用哪种条件取决于“模式”标志),sql,optimization,conditional,Sql,Optimization,Conditional,我用两种不同的方法解决了一个问题,但我想知道人们对这些选择有什么想法,以及他们是否还有其他选择 系统正在处理数据的“间隔” 所有数据都分配到一个“间隔” 间隔由事实表中的“interval\u start”日期时间表示 Dimension表包含“间隔”的持续时间(对于不同的实体可以不同) 维度表中还有一个“模式”标志 SQL查询中需要以下规则 模式0 如果事实表中有记录条目,则可以对其进行处理。 (没有限制。) 模式1 只有在“interval_start”为过去时,记录才对处理有效。 (

我用两种不同的方法解决了一个问题,但我想知道人们对这些选择有什么想法,以及他们是否还有其他选择

系统正在处理数据的“间隔”

  • 所有数据都分配到一个“间隔”
  • 间隔由事实表中的“interval\u start”日期时间表示
  • Dimension表包含“间隔”的持续时间(对于不同的实体可以不同)
  • 维度表中还有一个“模式”标志

SQL查询中需要以下规则

模式0
如果事实表中有记录条目,则可以对其进行处理。
(没有限制。)

模式1
只有在“interval_start”为过去时,记录才对处理有效。 (已经开始但不一定完成的时间间隔。)

模式2
只有当整个“间隔”都在过去时,记录才对处理有效。 (已完成的时间间隔。)


为此创建的第一个WHERE子句如下所示

WHERE
    getDate() >=
        CASE [table].mode
            WHEN 0 THEN 0
            WHEN 1 THEN [log].interval_start
            WHEN 2 THEN [log].interval_start + [table].interval_period
            ELSE        NULL
        END

有人担心这会妨碍索引优化该子句。另一种选择是使用多个和/或条件

WHERE
   ([table].mode = 0 AND getDate() >= 0)
OR ([table].mode = 1 AND getDate() >= [log].interval_start)
OR ([table].mode = 2 AND getDate() >= [log].interval_start + [table].interval_period)

显然,哪一种表现最好将取决于数据和索引等。但是,对于我目前所描述的“条件条件条件”,有人有任何意见或选择吗

干杯, Mat.

怎么样:

WHERE
     interval_start <= CASE mode
                         WHEN 0 THEN '9999-12-31'
                         WHEN 1 THEN GETDATE()
                         WHEN 2 THEN GETDATE() - interval_period
                       END
在哪里

interval_start另一个选项是运行三个单独的查询并将它们合并在一起。根据您的索引和表结构,这可能会导致比WHERE子句中的子句或USE CASE语句更高效的SQL,尽管这纯粹是在玩优化器的游戏


我将测试所有三种方法,并选择最适合您的方法。

我们考虑了该重构,假设通过将CASE语句限定为仅使用维度表中的字段,会有改进。收益很低,我们发现某些“小员工”[grin]无法理解getDate()-interval_period的结果。我们可能仍然会这样做,但会有很多评论:)@Tom:这已经有几个月了,但我必须指出,如果某一行的[mode]=0,您的代码在美国以外的大多数国家都会失败。令人难以置信的是,在使用day-month-year作为默认日期格式的语言环境中,“YYYY-AA-BB”被解释为B月,A日,如果它隐式转换为DATETIME或SMALLDATETIME(如此处所示),因为DATETIME是CASE表达式的类型。更疯狂的是,如果使用SYSDATETIME(并用DATEDIFF替换减法),就不会发生这种情况。这将把CASE表达式键入DATETIME2,它在所有语言环境中解释YYYY-MM-DD。考虑到我主张联合几个更简单的查询以避免一个慢得多的查询,我很惭愧在这种情况下没有想到它。谢谢你的提醒,我现在用一条湿漉漉的大鱼打自己的头作为惩罚……:)我很想知道这对你是否有效(工会,而不是用湿漉漉的鱼拍打……)如果能知道这是大多数此类查询的默认方法,还是仅仅是技巧袋中的另一个选项,那就太好了。目前数据集非常小,我预计联合速度会较慢。但我也希望数据集会增长几个数量级,然后我认为联合方法可能会更好。假设我记得在接下来的几周里,我会用我的发现补充另一条评论:)P.S.这条鱼是一条金枪鱼,因为它太大了,所以很痛,但在全麦面包上加一点海盐味道很好……案例选择非常差(我的最差,汤姆的下一个),而且在所有案例中都是最差的。AND/OR逻辑在较小的集合上最好,UNION逻辑在较大的集合上最好。(和/或每行引入较小的开销,UNION每被UNION的查询引入相对较大的开销。转折点在哪里取决于数据、逻辑和集合的大小)