nullnullnull
nullnullnull

Reputation: 8189

MySQL: Creating Multiple Variables with COALESCE

By using COALESCE, I can create a temporary variable called comment_votes like so:

SELECT comments.*, COALESCE(rs_reputations.value, 0) AS comment_votes FROM `comments` 
LEFT JOIN rs_reputations ON comments.id = rs_reputations.target_id AND 
rs_reputations.target_type = 'Comment' AND rs_reputations.reputation_name = 
'comment_votes' AND rs_reputations.active = 1 WHERE (impression_id = 1)

I want to create a second variable called impression_votes in the came query. I attempted to do this with:

SELECT comments.*, COALESCE(rs_reputations.value, 0) AS comment_votes 
FROM 'comments' 
    LEFT JOIN rs_reputations ON 
        comments.id = rs_reputations.target_id AND 
        rs_reputations.target_type = 'Comment' AND 
        rs_reputations.reputation_name = 'comment_votes' AND 
        rs_reputations.active = 1 
SELECT comments.*, COALESCE(rs_reputations.value, 0) AS impression_votes 
FROM 'comments' 
    LEFT JOIN rs_reputations ON 
    comments.id = rs_reputations.target_id AND
    rs_reputations.target_type = 'Comment' AND
    rs_reputations.reputation_name = 'impression_votes' AND 
    rs_reputations.active = 1 
WHERE

This leads to the error:

You have an error in your SQL syntax

Is what I'm attempting even possible? If so, I seem to be bridging the two SELECT/COALESCE statements improperly. How should I write this?

Upvotes: 1

Views: 2852

Answers (1)

dash
dash

Reputation: 91480

The MySQL COALESCE function is actually an inbuilt function that returns the first non-null value - it's not a variable, it's a function that is actually supported across a wide variety of database systems.

For example, with the following table:

| Id    | Name      | Counter    |
| 1     | lolcat    | NULL       |
| 2     | codez     | 1          |

The sql statement:

SELECT Id, Name, COALESCE(counter, 0) AS NonNullCounter FROM table

will return the results:

| Id    | Name      | NonNullCounter |
| 1     | lolcat    | 0              |
| 2     | codez     | 1              |

In this instance, the NULL value has been replaced by 0.

This is useful for you as, if you don't yet have any matching rows in rs_reputations for the row in comments, the LEFT JOIN will return NULL for the column rs_repuations.value, which is then replaced by 0 by COALESCE.

If you are new to JOINs then there is a great visual guide by Jeff Atwood.

Your first query can is actually:

SELECT     comments.*, 
           COALESCE(rs_reputations.value, 0) AS comment_votes 
FROM       comments 
LEFT JOIN   rs_reputations ON comments.id = rs_reputations.target_id 
                           AND rs_reputations.reputation_name = 'comment_votes' 
WHERE       impression_id = 1;

CHOICE 1 - UNION

You have a couple of choices - you can either UNION your results together like this:

SELECT     comments.*, 
           COALESCE(rs_reputations.value, 0) AS votes,
           'comment_votes' AS vote_type 
FROM       comments 
LEFT JOIN   rs_reputations ON comments.id = rs_reputations.target_id 
                           AND rs_reputations.reputation_name = 'comment_votes' 
WHERE       impression_id = 1

UNION

SELECT     comments.*, 
           COALESCE(rs_reputations.value, 0) AS votes,
           'impression_votes' as vote_type 
FROM       comments 
LEFT JOIN   rs_reputations ON comments.id = rs_reputations.target_id 
                           AND rs_reputations.reputation_name = 'impression_votes' 
WHERE       impression_id = 1;

In this instance your results will look like this:

|comments_columns|votes|vote_type       |
| *              |12   |comment_vote    |
| *              |2    |impression_vote |  

CHOICE 2 - JOIN ON TO THE SAME TABLE TWICE

Or you can self join onto the same table twice by using the same table name but a different alias:

SELECT     comments.*, 
           COALESCE(CommentRep.value, 0) AS comment_votes,
           COALESCE(ImpressionRep.value, 0) AS impression_votes,
FROM       comments 
LEFT JOIN   rs_reputations AS CommentRep ON comments.id = CommentRep.target_id 
                           AND CommentRep.reputation_name = 'comment_votes' 
LEFT JOIN   rs_reputations AS ImpressionRep ON comments.id = ImpressionRep.target_id 
                           AND ImpressionRep.reputation_name = 'impression_votes'
WHERE       CommentRep.impression_id = 1
AND         ImpressionRep.impression_id = 1

In this instance your results will look like this:

|comments_columns|comment_votes|impression_votes|
| *              |12           |0               |
| *              |2            |6               |  

Finally (phew) the reason you have an error in your original SQL is that you are chaining two SELECT statements together without actually relating them - the SQL doesn't really make sense in this instance as you need to logically relate them (either via a UNION or a repeated join as per above.

Upvotes: 2

Related Questions