Reputation: 11201
I have this query and result in my database:
mysql> SELECT id FROM jos_content
WHERE catid=12 AND state=1
AND DATE(publish_up) <= NOW() ORDER BY DATE(publish_up) DESC LIMIT 0,5;
+----+ | id | +----+ | 48 | | 47 | | 46 | +----+ 3 rows in set (0.00 sec)
Now I would like to count result:
mysql> SELECT count(*), id FROM jos_content
WHERE catid=12 AND state=1
AND DATE(publish_up) <= NOW() ORDER BY DATE(publish_up) DESC LIMIT 0,5;
+----------+----+ | count(*) | id | +----------+----+ | 3 | 46 | +----------+----+ 1 row in set (0.00 sec)
Why aren't the 48 and 47 results shown?
Thank you in advance
Upvotes: 2
Views: 165
Reputation: 270677
You need to include a GROUP BY
clause. By default, MySQL permits columns in the SELECT
clause which are not also included in a GROUP BY
(which is an error in most other RDBMS). Without the GROUP BY
, MySQL will return the first of the associated columns, which is often not the correct intended result.
SELECT
count(*),
id
FROM jos_content
WHERE catid=12 AND state=1 AND DATE(publish_up) <= NOW()
GROUP BY id
ORDER BY DATE(publish_up) DESC
LIMIT 0,5;
Not requiring all columns in the GROUP BY
is helpful if you want to return multiple columns in a summary which are always unique, as something like the following, where name
is unique to id
, but you MUST group at least one column for an aggregate to act correctly and produce a summary:
SELECT
id,
name,
COUNT(*)
FROM tbl
GROUP BY id
For compatibility with other RDBMS, and to avoid bugs, I recommend always including all the SELECT
columns in the GROUP BY
explicitly.
With better understanding of what you attempted, if you want the total count of all rows beside the id of each row, you can use a subselect like in the SELECT
list. This is going to be a bit slow though.
SELECT
id,
(SELECT COUNT(*) FROM jos_content) AS numitems
FROM jos_content
WHERE catid=12 AND state=1 AND DATE(publish_up) <= NOW()
ORDER BY DATE(publish_up) DESC
LIMIT 0,5;
You can trick this to work a little faster by doing a cartesian join (no ON
clause) against the count in a subquery, so it shouldn't get executed for each row. Only do this if the subquery will return exactly one row.
SELECT
id
numitems
FROM
jos_content
/* Join with no ON clause */
JOIN (SELECT COUNT(*) AS numitems FROM jos_content) subq
WHERE catid=12 AND state=1 AND DATE(publish_up) <= NOW()
ORDER BY DATE(publish_up) DESC
LIMIT 0,5;
Upvotes: 3
Reputation: 20765
Count is aggregate function, so if you want to include any of the column then that column must be part of group by clause in the query.
Upvotes: 0