简体   繁体   中英

MySQL COUNT records before GROUP BY

I'm working on a simple query over two tables and I'm trying to count the number of records with the same ID I would have got if I didn't group them. These are the tables:

TABLE jobs

id -- type -- user_id -- field_id

1 -- painting -- 53 -- 12

2 -- reading -- 53 -- 12

3 -- writing -- 53 -- 12

TABLE activities

id -- is_test -- user_id -- field_id

7 -- Yes -- 53 -- 12

8 -- No -- 53 -- 12

With this query I get the single record that I want from the table jobs (painting) because I'm using the GROUP BY clause on the column jobs.id . If I didn't use the GROUP BY, I would get 2 records because there are 2 matching activities for the same user_id and field_id .

SELECT `jobs`.*,`activities`.`is_test` 
FROM `jobs` 
LEFT JOIN `activities` ON `activities`.`user_id`=`jobs`.`user_id` 
WHERE `jobs`.`field_id`=12 AND `activities`.`field_id`=12 AND `jobs`.`type`='painting' AND `jobs`.`user_id`=53 
GROUP BY `jobs`.`id` 
ORDER BY `jobs`.`id` DESC;

What I'm trying to do is to fetch another column containing the actual number of matching records in the table activities . Basically I want to get 2 as count of records in activities with the same user_id and field_id .

I have tried to select the new column like this:

SELECT `jobs`.*,`activities`.`is_test`, COUNT(DISTINCT `jobs`.`id`) AS `tot_act` 

but this obviously returns 1 rather than 2 for the new column tot_act . Making it count the field activities.is_test did not work either.

I was trying to avoid a sub-select .

Please do not pay attention to the column activities.is_test , I don't care to see if it's set to Yes or No, I just want to count that there is a matching record for Yes and one for No so 2 records in total if I don't group them. 2 is the value I'm trying to retrieve as a new column.

Any ideas will be much appreciated!

Your first query doesn't make any sense. Group by only has meaning combined with an aggregate function in the output columns (select clause).

The where filter on activities.field_id is (expensively) converting the left join into an inner join.

I also suspect your schema is not normalised.

to fetch another column containing the actual number of matching records in the table activities

SELECT `jobs`.id, jobs.type, jobs.user_id, 
  Jobs.field_id,`activities`.`is_test`, 
  SUM(IF(activities.id IS NULL, 0,1)) 
FROM `jobs` 
 LEFT JOIN `activities` 
 ON `activities`.`user_id`=`jobs`.`user_id` 
 AND activities.field_id=12
WHERE `jobs`.`field_id`=12 
 AND `jobs`.`type`='painting' 
 AND `jobs`.`user_id`=53 
GROUP BY `jobs`.id, jobs.type, jobs.user_id, 
  Jobs.field_id,`activities`.`is_test`
ORDER BY `jobs`.`id` DESC;

COUNT() increments by 1 for each NON NULL value it encounters.

In your case you want the count of rows from the activities table, not the jobs table.

SELECT
      jobs.id
    , jobs.type
    , jobs.user_id
    , Jobs.field_id
    , COUNT(activities.id) activity_count
FROM jobs
      LEFT JOIN activities ON jobs.user_id = activities.user_id
                  AND activities.field_id = 12
WHERE jobs.field_id = 12
      AND jobs.type = 'painting'
      AND jobs.user_id = 53
GROUP BY
      jobs.id
    , jobs.type
    , jobs.user_id
    , Jobs.field_id
ORDER BY
      jobs.id DESC;

from your sample data that query produces this result:

| id |     type | user_id | field_id | activity_count |
|----|----------|---------|----------|----------------|
|  1 | painting |      53 |       12 |              2 |

Note however that if you include activity.is_test in the select and grouping clauses then you will not get a count of 2.

see this sqlfiddle

SELECT
  `jobs`.id,
  `jobs`.type,
  `jobs`.user_id,
  `jobs`.field_id,
  count(1) as activities_count,
  max(`activities`.is_test) as is_test
FROM
  `jobs`
LEFT OUTER JOIN
  `activities` ON
  `activities`.user_id = `jobs`.user_id
  AND `activities`.field_id = `jobs`.field_id
WHERE
  `jobs`.field_id = 12
  AND `jobs`.type = 'painting'
  AND `jobs`.user_id = 53
GROUP BY
  `jobs`.id,
  `jobs`.type,
  `jobs`.user_id,
  `jobs`.field_id

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