简体   繁体   中英

SQL Query: is 2nd clause filtered by 1st clause?

I have the following query:

SELECT users.id FROM sprints INNER JOIN users on (sprints.user_id = users.id )
WHERE sprints.user_id IN (1,2,3)
AND sprints.created_at BETWEEN x AND y
GROUP BY users.id HAVING COUNT(sprints.id) > 2

Does the HAVING COUNT(sprints.id) > 2 part refer to having >2 sprints that were created at between x and y ? Or does it refer to just having 2 sprints in general (regardless of creation date) ?

Or in other words, is the 2nd part of the query filtered down to the results of the first query? If not, how would I do that?

GROUP BY is evaluated after applying the filters on the WHERE clauses.

Therefore at the time of GROUP'ING, the filter conditions

WHERE sprints.user_id IN (1,2,3)
AND sprints.created_at BETWEEN x AND y

are already applied.

Next step is evaluating the HAVING clause.

We got the GROUPED record set at this stage, after that the filter on the HAVING clause is applied

HAVING COUNT(sprints.id)>2

Edit: From the comments, the OP asks options on how to show up records that

  • a) have sprints between times x and y
  • b) have 2 sprints (but those 2 sprints don't necessarily need to be between x and y)

Here, the conditions need to be applied without the filter conditions. Therefore we first "conditionally" count by using a case expression as below.

COUNT(CASE WHEN sprints.created_at BETWEEN x AND y THEN 
                1 
       END)

This count expression "counts" if the sprints created_at date lies between x and y. The COUNT(*) column counts regardless of any condition.

Now that we have the two metrics, we filter the record set, to satisfy

Bring only records where we have "sprints between times x and y" AND "have 2 sprints"

   WHERE cnt_of_sprints_between_x_and_y >0
     AND cnt_of_sprints >0

Final query

  WITH DATA
        AS (
       SELECT users.id
              ,COUNT(CASE WHEN sprints.created_at BETWEEN x AND y THEN 
                                1 
                      END) as cnt_of_sprints_between_x_and_y
              ,COUNT(*) as cnt_of_sprints
         FROM sprints 
        INNER JOIN users 
           ON (sprints.user_id = users.id )
        WHERE sprints.user_id IN (1,2,3)
    GROUP BY users.id 
        )
  SELECT id
    FROM data
   WHERE cnt_of_sprints_between_x_and_y >0
     AND cnt_of_sprints >0

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