如何从逻辑网格布局有效地产生正确的If / Else或CASE

时间:2020-09-09 19:26:37

标签: sql if-statement conditional-statements case

如何使用网格来提供有效的简洁代码?如果不使用网格,是否有更好的方法来处理条件逻辑,我是否使用正确的术语来描述我的问题?

当我看到根据多个变量返回的值生成条件逻辑输出时,我经常会深入研究并开始编码,但是据我所知,这不是正确的方法。当呈现复杂的逻辑路径时,经验丰富的前受过训练的人又如何提出简洁而有效的条件逻辑?

例如,根据变量A,B,C,D中的值,我可能具有以下可能的状态结果。就我而言,这是我当前正在执行的请求的非常简化的示例。状态值仅基于请求。例如,将第一行放到所有值= 1的单词中,它可能会读取如下内容:“当条件A,B和C为TRUE ...如果满足条件D,则将Status设置为'T',否则将其设置为' A'”。

用通俗易懂的英语阅读条件逻辑可能会很痛苦,因此我编译了一个网格,列出了产生所请求“状态”的可能条件。

enter image description here

如何使用网格来提供有效的简洁代码?

下面是我的模拟尝试,但这只是我的一次潜水,不能让我获得最有效的路线

WITH conditions AS
(
    SELECT 1 AS A, 1 AS B, 1 AS C, 1 AS D, 'T' AS desiredStatus UNION ALL
    SELECT 1, 1, 1, 0, 'A' UNION ALL
    SELECT 1, 1, 0, 0, 'A' UNION ALL
    SELECT 1, 0, 1, 1, 'H' UNION ALL
    SELECT 1, 0, 1, 0, 'H' UNION ALL
    SELECT 1, 0, 0, 0, 'A' UNION ALL
    SELECT 0, 1, 1, 1, 'H' UNION ALL
    SELECT 0, 1, 1, 0, 'H' UNION ALL
    SELECT 0, 0, 1, 1, 'H' UNION ALL
    SELECT 0, 0, 1, 0, 'H'
)
SELECT A, B, C, D, desiredStatus, 
   CASE WHEN A > 0 AND B > 0 THEN CASE WHEN C > 0 AND D > 0 THEN 'T' ELSE 'A' END 
        WHEN A > 0 AND B = 0 THEN 'H'
   END AS codedStatus
FROM conditions

2 个答案:

答案 0 :(得分:1)

由于标量表达式的计算很简单,尤其是与联接,索引扫描,范围查找等进行比较时,首要的考虑因素应该是可读性和可维护性。

可以写的是二进制搜索...

CASE WHEN a > 0 THEN
  CASE WHEN b > 0 THEN
    CASE WHEN c > 0 THEN
      CASE WHEN d > 0 THEN
        'T'
      ELSE
        'A'
      END
    ELSE
      CASE WHEN d > 0 THEN
        NULL
      ELSE
        'A'
      END
    END
  etc
etc

但这不是人类可读的,这是一个发现了二叉树的极客的幻想。


一个人可以剖析数据并使最有可能的情况出现在第一位...

CASE WHEN a = 0                     THEN 'H'
     WHEN b = 0 AND c = 1           THEN 'H'
     WHEN c = 0                     THEN 'A'
     WHEN d = 0                     THEN 'A'
     WHEN b = 1 AND c = 1 AND d = 1 THEN 'T' END

但是,您是否注意到其中存在错误?有一个,我故意把它放在那里,我挑战你去找到它,甚至更烦人了。纠正它。

(提示,某些组合未映射,应隐式为NULL。)


由于这些原因,我更喜欢映射表。代码简洁明了,易于维护(只需编辑表) ,隐式NULL受到照顾,并且错误很难掩盖。

SELECT
  yourTable.*,
  yourMap.val
FROM
  yourTable
LEFT JOIN
  yourMap
    ON  yourMap.A = yourTable.A
    AND yourMap.B = yourTable.B
    AND yourMap.C = yourTable.C
    AND yourMap.D = yourTable.D

该地图非常小,可以对其进行索引,并且整个索引可以在一次读取中读取,然后保存在内存中。

也许在高速事务环境中会编码逻辑而不是将其存储为数据。但是在所有其他环境中,代码可维护性在十分之九的优势中胜出。


即使在高速交易环境中,我也会列举每种组合,而不是尝试折叠代码...

CASE
  WHEN a=0 AND b=0 AND c=0 AND d=0 THEN NULL
  WHEN a=0 AND b=0 AND c=0 AND d=1 THEN NULL
  WHEN a=0 AND b=0 AND c=1 AND d=0 THEN 'H'
  WHEN a=0 AND b=0 AND c=1 AND d=1 THEN 'H'
  etc
END

K.I.S.S。

答案 1 :(得分:1)

网格大部分为“ H”结果,因此我仔细研究了两种不同的情况。在您的情况下,我立即注意到从1到0的单调下降。

case
    when A * B * C * D = 1 then 'T'
    when A = 1 and A >= B and B >= C and C >= D then 'A'
    when A + B < 2 and C = 1 else 'H'
    else 'I'
end

case
    when A >= B and B >= C and C >= D then
        case when D = 1 then 'T' when A = 1 then 'A'
    when not (A = 1 and B = 1) and C = 1 then 'H'
    else 'I'
end

我不知道我是否会使用这种方法。可读性显然是一个考虑因素。它对四个输入变量应用“大于”隐喻是否有助于您的思考?还是将“ H”的情况减少为“必须具有C且决不能同时包含A和B”?我认为这些似乎很可能会翻译回普通的英语。

此重新排序的矩阵有助于选择模式。

Logic table

相关问题