Ian McInerney
Ian McInerney

Reputation: 31

Why is SQLite conditional between generated variables not comparing correctly?

I'm a little confused why I'm getting results in the following example. Let's pretend that we want to rank how much someone likes animals. They like any colored tiger best, red animals second, and doesn't like any others.

Consider the following table:

----------------------
| Color  | Animal    |
----------------------
| Yellow | Butterfly |
| Red    | Lion      |
| Red    | Tiger     |
| Green  | Lion      | 
| Green  | Donkey    |
| Yellow | Tiger     |
----------------------

Now when I run this code:

CREATE VIEW animal_colors as select "farm"."color" as "color",
CASE WHEN "farm"."color" = 'Red' THEN 1 ELSE 0 END AS "color_red",
CASE WHEN "farm"."animal" = 'Tiger' THEN 1 ELSE 0 END AS "animal_tiger",
CASE
    WHEN "animal_tiger" = 1 THEN 1
    WHEN "color_red" = 1 THEN 0
    ELSE -1
END 
AS "rank"

FROM "farm"

I get the following output:

----------------------------------------------------------
| Color  | Animal    | color_red | animal_tiger | rank  |
---------------------------------------------------------
| Yellow | Butterfly | 0         | 0            | -1    |
| Red    | Lion      | 1         | 0            | -1    |
| Red    | Tiger     | 1         | 1            | -1    |
| Green  | Lion      | 0         | 0            | -1    |
| Green  | Donkey    | 0         | 0            | -1    |
| Yellow | Tiger     | 0         | 1            | -1    |
---------------------------------------------------------

I thought I was comparing the variables color_red and animal_tiger to see if they are 1, but it doesn't look like that is happening. Could anyone shed some light on why the expression is always evaluating as -1?

Upvotes: 1

Views: 43

Answers (2)

webmite
webmite

Reputation: 575

Try this. I originally had the syntax incorrect for the muli-when case statement.

CREATE VIEW "animal_colors" as select "farm"."color" as "color",
 CASE WHEN "farm"."color" = 'Red' THEN 1 ELSE 0 END AS "color_red",
 CASE WHEN "farm"."animal" = 'Tiger' THEN 1 ELSE 0 END AS "animal_tiger",
 CASE WHEN "farm"."animal" = 'Tiger' THEN 1
      WHEN "farm"."color" = 'Red' THEN 0
      ELSE -1 END as "rank" 
FROM "farm"

which yields

color       color_red   animal_tiger    rank
"Yellow"    "0"         "0"             "-1"
"Red"       "1"         "0"             "0"
"Red"       "1"         "1"             "1"
"Green"     "0"         "0"             "-1"
"Green"     "0"         "0"             "-1"
"Yellow"    "0"         "1"             "1"

Upvotes: 2

MikeT
MikeT

Reputation: 56948

You are comparing "animal_tiger" (a string) to 'Tiger' which will not be true.

To access the derived columns animal_tiger and color_red you need to make the select a subquery, or use the actual columns.

So you could use either (not using derived columns) :-

SELECT farm.color AS color,
    CASE
        WHEN farm.color = 'Red' THEN 1 ELSE 0 END AS color_red,
    CASE 
        WHEN farm.animal = 'Tiger' THEN 1 ELSE 0 END AS animal_tiger,
    CASE 
        WHEN farm.animal = 'Tiger' THEN 1
        WHEN farm.color = 'Red' THEN 0
        ELSE -1
        END AS rank
FROM farm;

resulting in

enter image description here

or (using derived columns via a subquery) :-

SELECT *, 
    CASE 
        WHEN animal_tiger = 1 THEN 1
        WHEN color_red = 1 THEN 0
        ELSE -1
        END AS rank
 FROM (
    SELECT "farm"."color" as "color",
    CASE WHEN "farm"."color" = 'Red' THEN 1 ELSE 0 END AS "color_red",
    CASE WHEN "farm"."animal" = 'Tiger' THEN 1 ELSE 0 END AS "animal_tiger"
    FROM "farm"
);

Resulting in :-

enter image description here

Note done as SELECTS rather than creating VIEWS for my convenience

Additional

Perhaps you could simplify using the following as the basis :-

SELECT farm.color AS color, 
    -1 + (farm.color = 'Red') + (farm.animal = 'Tiger') AS rank 
FROM farm

This yields :-

enter image description here

Or perhaps even

SELECT farm.color AS color, 
    0 + (farm.color = 'Red') + ((farm.animal = 'Tiger') * 2) AS rank 
FROM farm

(giving a ranking base of zero and giving tiger a higher rank then red thus you could easily discriminate say between a red and yellow tiger, the former having a higher rank)

This would yield :-

enter image description here

Upvotes: 3

Related Questions