简体   繁体   中英

CASE WHEN PostgreSQL only working for one case

I'm writing a query that will go into some golang backend code to autopopulate some billing fields that we have. Basically there's a standard fee and a reduced fee. There's a table of these fees, the ID number, and the effective date.

If the ID number is in the list, I want to just select the fee for that ID number. If the ID number is not in the list, I want to select the standard fee.

On the statements we get, we are given the MemberID. The MemberID joins with a CorporateID (CorpID) in a CorporateLinks table. If the MemberID is not in the CorporateLinks table at all, I want to select the standard fee.

Here is my query:

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;

When the MemberID maps to a CorpID and the CorpID is in the list, it returns it perfectly. When the MemberID is NOT in CorporateLinks, it returns an empty field. I haven't found a test case where the MemberID is in CorporateLinks but CorpID is not in ConversionFactor ( ELSE Case).

I'm not sure where I'm going wrong. I'm not very well versed in using CASE WHEN statements in queries, I've only used them in functions before to perform regex operations.

There are several questionable things about your query.

The parts relevant to the discussion look like:

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

Observations:

  1. There can be only a single value of conversionfactor in each group, because that column is part of the GROUP BY clause.

    So it makes no sense to write max(conversionfactor) - it is going to be the same as conversionfactor .

  2. The second THEN branch and the ELSE branch both return max(conversionfactor) , so the second WHEN clause is superfluous.

Since all three branches return the same value, the whole CASE expression can be replaced with conversionfactor , because that is always going to be the result.

But your actual question is why the CASE expression returns an "empty field".

From the above discussion that would mean that conversionfactor is either an empty string (if it is a string type) or NULL.

Now there is no reason why this shouldn't be the case. You have to examine your data and look for NULL values or empty strings in that column. The CASE expression is useless, but it is not at fault for that.

You want to use a LEFT JOIN . The default join type if you don't specify is an INNER JOIN , and so if there is no entry in ConversionFactor that matches, the result set will omit it completely, not just set the relevant column(s) to NULL . Also your WHERE clause explicitly filters for MemberId . If MemberId is NULL , you'll never see any results as a result either.

You are also using sub-selects when it's not clear you need them. Once you switch to the LEFT JOIN see what the output looks like with a simple selection:

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

Once you can see your whole result set, it should be easier to work out how you want to filter and aggregate later by editing which columns you want returned.

It's quite possible that you don't need the CASE statement at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM