PostgreSQL仅适用于一种情况的情况

时间:2019-12-20 18:32:09

标签: sql postgresql switch-statement case

我正在编写一个查询,该查询将进入一些golang后端代码中,以自动填充我们拥有的某些计费字段。基本上有标准费用和减价费用。表格中列出了这些费用,ID号和生效日期。

如果该ID号在列表中,我只想选择该ID号的费用。 如果ID号码不在列表中,我想选择标准费用。

在得到的语句上,我们得到了MemberID。 MemberID与CorporateLinks表中的CorporateID(CorpID)联接。如果完全没有CorporateLinks表中的MemberID是 ,我想选择标准费用。

这是我的查询:

SELECT
CASE
WHEN cl.CorpID IN (SELECT CorpID FROM ConversionFactor) THEN MAX(cf.ConversionFactor)
WHEN MemberID NOT IN (SELECT MemberID FROM CorporateLinks) THEN MAX(cf.ConversionFactor)
ELSE MAX(cf.ConversionFactor) 
END 
FROM ConversionFactor cf
LEFT JOIN CorporateLinks cl
ON cf.CorpID = cl.CorpID
WHERE EffectiveDate = (SELECT EffectiveDate FROM ConversionFactor
                       WHERE EffectiveDate < $2
                       ORDER BY EffectiveDate DESC LIMIT 1)
AND MemberID = $1
GROUP BY cl.CorpID, cl.MemberID;

当MemberID映射到CorpID并且CorpID在列表中时,它会完美返回。 当MemberID不在CorporateLinks中时,它将返回一个空字段。 我还没有找到MemberID在CorporateLinks中但CorpID不在ConversionFactor中的测试案例(ELSE案例)。

我不确定我要去哪里。我对查询中使用CASE WHEN语句不是很精通,在执行正则表达式操作之前,我仅在函数中使用过它们。

2 个答案:

答案 0 :(得分:0)

关于您的查询有一些可疑的事情。

与讨论相关的部分如下:

SELECT CASE WHEN ... IN (SELECT ...)
            THEN conversionfactor
            WHEN ... NOT IN (SELECT ...)
            THEN max(conversionfactor)
            ELSE max(conversionfactor)
       END
FROM ...
GROUP BY ..., conversionfactor, ...;

观察:

  1. 每个组中只能有一个conversionfactor值,因为该列是GROUP BY子句的一部分。

    因此写max(conversionfactor)毫无意义-它将与conversionfactor相同。

  2. 第二个THEN分支和ELSE分支都返回max(conversionfactor),因此第二个WHEN子句是多余的。

由于所有三个分支都返回相同的值,因此整个CASE表达式可以替换为conversionfactor,因为这始终是结果。

但是您的实际问题是,为什么CASE表达式返回一个“空字段”。

根据以上讨论,这意味着conversionfactor是空字符串(如果是字符串类型)或NULL。

现在没有理由不应该这样了。您必须检查数据并在该列中查找NULL值或空字符串。 CASE表达式没有用,但这并不是错误。

答案 1 :(得分:-1)

您要使用LEFT JOIN。如果未指定,则默认联接类型为INNER JOIN,因此,如果ConversionFactor中没有匹配的条目,结果集将完全忽略它,而不仅仅是设置相关列)到NULL。此外,您的WHERE子句还明确过滤了MemberId。如果MemberIdNULL,那么您也永远不会看到任何结果。

在不清楚您是否需要子选择时,您还将使用子选择。切换到LEFT JOIN后,只需进行简单选择即可查看输出:

SELECT cf.*, cl.*
FROM ConversionFactor cf
  LEFT JOIN CorporateLinks cl USING (CorpID)
WHERE cf.EffectiveDate < $2
LIMIT 100 -- Limit for a sanity check to prevent too many results as you debug

一旦您可以看到整个结果集,通过编辑要返回的列,可以更容易地弄清楚以后如何过滤和汇总。

很有可能根本不需要CASE语句。