Multiple counts within a single SQL query

I’m trying to get the count of documents within 4 specific sections using the following code:

SELECT
    category.id
    , category.title
    , count(ts1.section_id) AS doc1
    , count(ts2.section_id) AS doc2
    , count(ts3.section_id) AS doc3
    , count(ts4.section_id) AS doc4
FROM
    category 
    LEFT JOIN category_link_section AS ts1
        ON (category.id = ts1.category_id AND ts1.section_id = 1)
    LEFT JOIN category_link_section AS ts2
        ON (category.id = ts2.category_id AND ts2.section_id = 2)
    LEFT JOIN category_link_section AS ts3
        ON (category.id = ts3.category_id AND ts3.section_id = 3)
    LEFT JOIN category_link_section AS ts4
        ON (category.id = ts4.category_id AND ts4.section_id = 4)
GROUP BY category.id, ts1.section_id, ts2.section_id, ts3.section_id, ts4.section_id

The table ‘category’ had an id, title etc.
The table ‘category_link_section’ contains id linkages between category_id, section_id, and doc_id.

If the count is 0 for any column, it displays 0 in that column. But if the result is not 0 it shows the multiplication result of all the section results. So if my 4 count columns were supposed to return: 1, 2, 0, 3; it would actually show 6, 6, 0, 6;

If I use this following code for each specific category I get the results I want:

SELECT
    category.id
    , category.title
    , count(ts1.section_id) AS doc1
FROM
    category 
    LEFT JOIN category_link_section AS ts1
        ON (category.id = ts1.category_id AND ts1.section_id = 1)
GROUP BY category.id, ts1.section_id

but I then need to cycle through the database each time for each section.

So my question is, do I need to step through and call each section in turn, constructing my table outside the SQL, or can this be done in a single query?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

@VoteyDisciple’s answer is on the right track, but his query needs some improvements:

SELECT c.id, c.title,
    SUM(ts1.section_id = 1) AS doc1,
    SUM(ts1.section_id = 2) AS doc2,
    SUM(ts1.section_id = 3) AS doc3,
    SUM(ts1.section_id = 4) AS doc4
FROM category AS c
  LEFT JOIN category_link_section AS ts1
    ON (c.id = ts1.category_id)
GROUP BY c.id;

Explanations:

  • The IF() expressions are redundant because equality already returns 1 or 0.
  • Take the ts1.section_id=1 out of the join condition, or you’ll never get the other section_id values.
  • Group by c.id only. I assume the OP only wants one row per category, and columns for counts of each section_id value for the respective category. If the query grouped by c.id, ts1.section_id, then there’d be up to four rows per category.
  • Move the commas in the select-list. Commas floating at the start of the line look ugly. 😉

Method 2

You might want to try something like this:

SELECT
    category.id
    , category.title
    , SUM(IF(ts1.section_id = 1, 1, 0)) AS doc1
    , SUM(IF(ts1.section_id = 2, 1, 0)) AS doc2
    , SUM(IF(ts1.section_id = 3, 1, 0)) AS doc3
    , SUM(IF(ts1.section_id = 4, 1, 0)) AS doc4
FROM
    category 
    LEFT JOIN category_link_section AS ts1
        ON (category.id = ts1.category_id AND ts1.section_id = 1)
GROUP BY category.id, ts1.section_id


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x