I need to create a select query with count from another table.
I have two tables like category and candidates. Every candidate belong to one category.
Here I want to select all categories from category table along with how many candidates available for each category.
like this: category_name(23)
This is how I tried it. but it doesn't work for me.
SELECT c.category_id
, c.name
, COUNT(cn.job_category) AS cvs
FROM job_category c
LEFT JOIN candidates cn ON cn.job_category = c.category_id
ORDER BY c.name ASC
You are missing the group by clause.
SELECT c.category_id
, c.name
, COUNT(cn.job_category) AS cvs
FROM job_category c
LEFT JOIN candidates cn ON cn.job_category = c.category_id
GROUP BY c.category_id
, c.name
ORDER BY c.name ASC
Note: Without group by, mysql will just return an arbitrary category. It allows this behavior while most other database systems would result in an error when you don't include non-aggregated columns in the group by clause.
Related
I want to group order's count to show how many clients have that number of orders.
I have come up with:
select count(*) as quantidade_pedidos, clientes.id
from pedidos
inner join clientes
on pedidos.cliente_id = clientes.id
where pedidos.aprovado = 1
group by quantidade_pedidos
but I just can't group by 'quantidade_pedidos' anyway.
Is there any way to group by a temporary column? Another way of doing this? show how many clients (number) have that number of orders placed?
Example
8 orders placed -> 3 clients have 8 orders placed
etc
Your original query is wrong. You need to group by clientes.id:
select count(*) as quantidade_pedidos, c.id
from pedidos p inner join
clientes c
on p.cliente_id = c.id
where p.aprovado = 1
group by c.id;
In an aggregation query, the unaggregated columns go in the group by, not the aggregated ones.
Also note that table aliases make the query easier to write and to read.
As for the question in the first line, use a subquery:
select quantidade_pedidos, count(*)
from (select count(*) as quantidade_pedidos, c.id
from pedidos p inner join
clientes c
on p.cliente_id = c.id
where p.aprovado = 1
group by c.id
) x
group by quantidade_pedidos;
But given that the query in the question doesn't work, I'm not sure this is what you really want to do.
I have this query that will return a list of all of the people associated with Thomas and their ids.
SELECT c.name, c.ID
FROM namesandID s, associations o, namesandID c
WHERE s.name='Thomas' AND o.id = s.ID AND o.associateID = c.ID
GROUP BY c.ID;
Then I have this query that I can manually type in the id number and it will return the correct count of associates.
SELECT count(*) FROM (
SELECT associateID FROM associations WHERE id=18827 GROUP BY associateID
) AS t;
My goal is to have one query that will take Thomas as the name and return three columns that will have his associate their id number an the number of people they are associated with.
Also as some additional information this is a very large database with about 4million rows and 300million associations so any speed increase on either of these queries would be greatly welcomed.
Not tested, however the below should work:
select
c.name,
c.id,
assoc_count.cnt
from
namesandIds s
inner join
associations o on
o.id = s.ID
inner join
namesandId c on
c.ID = o.associateId
left outer join
(
select
id,
count(distinct associateId) as cnt
from
associations
group by
id
) assoc_count on
assoc_count.id = c.ID
where
s.name = 'Thomas'
Not very efficient but
SELECT c.name, c.ID, COUNT(DISTINCT o.associateID)
FROM {the rest of the first query}
should do the trick.
I have 3 tables :
user(id, name);
advert(id,name,category_id,user_id);
category(id,category_name);
What i want to do is show for a certain user how many adverts he has in each category.
I have to use a sub-query.I've tried something like this but is not working at all.
What I've tried looks like this:
SELECT c.id,c.name count(advert) number_of_adverts
FROM category c
GROUP BY c.name
HAVING count(advert)=(SELECT count(a.id)
FROM advert a
INNER JOIN user ON a.user_id=u.id
WHERE u.id="1"
HAVING a.category_id=c.id);
I know this is wrong but i dont quite understand how should i do it to make it work.
Your looking for the GROUP BY clause.
SELECT c.id, c.name, COUNT(a.id) AS number_of_adverts
FROM user u
JOIN advert a ON (u.id = a.user_id)
JOIN category c ON (c.id = a.category_id)
WHERE u.user_id = '999'
GROUP BY c.id, c.name
You can't use a sub-query as, there could be multiple categories and multiple adverts for each category.
I'm trying to clean a db with duplicate records. I need to move the reference to a single record and delete the other one.
I have two tables: Promoters and Venues, each has a reference to a table called cities. The problem is that there are cities with the same name and different ids, that have a relation with venues and promoters.
With this query I can group all promoters and venues with a single city record:
SELECT c.id as id, c.name as name, GROUP_CONCAT( DISTINCT p.id ) as promoters_ids, GROUP_CONCAT( DISTINCT v.id ) as venues_ids
FROM cities as c
LEFT JOIN promoters as p ON p.city_id = c.id
LEFT JOIN venues as v ON v.city_id = c.id
WHERE c.name IN ( SELECT name from cities group by name having count(cities.name) > 1 )
GROUP BY c.name
Now I want to run an UPDATE query on promoters, setting the city_id equals to the result of the query above.
Something like this:
UPDATE promoters AS pr SET pr.city_id = (
SELECT ID
FROM (
SELECT c.id as id, c.name as name, GROUP_CONCAT( DISTINCT p.id ) as promoters_ids
FROM cities as c
LEFT JOIN promoters as p ON p.city_id = c.id
WHERE c.name IN ( SELECT name from cities group by name having count(cities.name) > 1 ) AND pr.id IN promoters_ids
GROUP BY c.name
) AS T1
)
How can I do this?
Thanks
If I understand correctly, you want to remove duplicate cities (in the end), so you need to update promoters that are linked to any of the cities you want to remove in that process.
I think it makes sense to use the lowest ID of any of the cities with the same name (could be the highest just as well, but I want to specify it at least, and don't leave it up to me.
So in order get the right ID for a promoter, I need to: Select the lowest ID of all cities that have the same name as the city already linked to a promoter.
Fortunately, that demand fits snuggly into a query:
UPDATE promoters AS pr
SET pr.city_id = (
SELECT
-- Select the lowest ID ..
Min(c.id)
FROM
-- .. of all cities ..
Cities c
-- .. that have the same name ..
INNER JOIN Cities pc on pc.Name = c.Name
WHERE
.. as the city already linked to the promoter being updated
pc.id = pr.city_id
GROUP BY
c.name)
The trick is to join Cities on itself by name, so you can easily get all cities with the same name. I think you tried the same with the IN clause, but that's a little more complex than it needs to be.
I don't think you need group_concat at all, besides checking if the inned query returns the correct cities indeed, although it doesn't make sense, since you're already grouping on the name. When written like this, you can tell that there should be no way that this can go wrong:
SELECT
-- Select the lowest ID ..
MIN(c.id) AS id,
GROUP_CONCAT(c.name) AS names --< already grouped by this, so why...
FROM
-- .. of all cities ..
Cities c
-- .. that have the same name.
INNER JOIN Cities pc on pc.Name = c.Name
GROUP BY
c.name
I hope I understood the question correctly.
I have three tables tl_log, tl_geo_countries,tl_purpose. I am trying to get the count of number of days spent in each country in table 'tl_log' for each purpose in table 'tl_purpose'.
I tried below mysql query
SELECT t.country_id AS countryID,t.reason_id AS reasonID,count(t.reason_id) AS
days,c.name AS country, p.purpose AS purpose
FROM `tl_log` AS t
LEFT JOIN tl_geo_countries AS c ON t.country_id=c.id
LEFT JOIN tl_purpose AS p ON t.reason_id=p.id
GROUP BY t.reason_id,t.country_id ORDER BY days DESC
But landed up with.
I am not able to get the count for purpose for each country in 'tl_log' that is not present in table 'tl_log'. Any help is greatly appreciated. Also, Please let me know if the question is difficult to understand.
Expected Output:
Below is the structure of these three tables
tl_log
tl_geo_countries
tl_purpose
If you want all possible combination of countries and purposes, even those that do not appear on the log table (these will be shown with a count of 0), you can do first a cartesian product of the two tables (a CROSS join) and then LEFT join to the log table:
SELECT
c.id AS countryID,
p.id AS reasonID,
COUNT(t.reason_id) AS days,
c.name AS country,
p.purpose AS purpose
FROM
tl_geo_countries AS c
CROSS JOIN
tl_purpose AS p
LEFT JOIN
tl_log AS t
ON t.country_id = c.id
AND t.reason_id = p.id
GROUP BY
p.id,
c.id
ORDER BY
days DESC ;
If you want the records for only the countries that are present in the log table (but still all possible reason/purposes), a slight modification is needed:
SELECT
c.id AS countryID,
p.id AS reasonID,
COUNT(t.reason_id) AS days,
c.name AS country,
p.purpose AS purpose
FROM
( SELECT DISTINCT
country_id
FROM
tl_log
) AS dc
JOIN
tl_geo_countries AS c
ON c.id = dc.country_id
CROSS JOIN
tl_purpose AS p
LEFT JOIN
tl_log AS t
ON t.country_id = c.id
AND t.reason_id = p.id
GROUP BY
p.id,
c.id
ORDER BY
days DESC ;
LEFT JOIN should be replaced by RIGHT JOIN