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.
Related
I have 2 tables: Projects and custom_values which are linked by the project id.
I did this inner join query
SELECT custom_values.customized_id ,custom_values.custom_field_id,
custom_values.value FROM projects INNER JOIN custom_values ON
projects.id=custom_values.customized_id order by custom_values.customized_id asc
You will find the responce of this query in the file joined.
I want to know if there is a way to group those rows by customized_id field.
By the way I tried Group by but it doesn't work
If you want group you need a aggregation function eg (max, min group_concat) and group by , if you want all the values related to a customized_id on a row you could use group_concat eg:
SELECT custom_values.customized_id
,group_concat(custom_values.value )
FROM projects
INNER JOIN custom_values ON projects.id=custom_values.customized_id
GROUP BY custom_values.customized_id
order by custom_values.customized_id asc
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 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
This query is working fine. It gives a count of contest entrants for whom the contact id in contest_entries is their origin_contact in the person table.
SELECT c.handle, COUNT(*)
FROM `contest_entry` ce,
person p,
contest c
WHERE
p.origin_contact = ce.contact AND
c.id = ce.contest
GROUP BY c.id
I want to now query how many of those records also have at least one record where the contact id matches in email_list_subscription_log BUT that table may have many log records for any one contact id.
How do I write a join that gives me a count that is not inflated by the multiple records?
Should I use a version of my first query to get all of the contact ids into a tmp table and just use that?
Not sure which field is contact id, but you can do something like this:
select c.handle,
count(*) as count
from `contest_entry` ce
inner join person p on p.origin_contact = ce.contact
inner join contest c on c.id = ce.contest
where exists (
select 1
from email_list_subscription_log l
where l.contact_id = ce.contact
)
group by c.id
You ought to deflate the email_list_subscription_log with DISTINCT or GROUP:
SELECT c.handle, COUNT(*)
FROM `contest_entry` ce
JOIN person p ON (p.origin_contact = ce.contact)
JOIN contest c ON (c.id = ce.contest)
JOIN (SELECT DISTINCT contact, email FROM email_list_subscription_log ) AS elsuniq
ON (ce.contact = elsuniq.contact)
[ WHERE ]
GROUP BY c.id
Using GROUP in the subquery you might count the number of records while still returning one row per element:
JOIN (SELECT contact, count(*) AS elsrecords FROM email_list_subscription_log
GROUPY BY contact) AS elsuniq
With this JOIN syntax, the WHERE is not necessary, but I kept it there if you need additional filtering.
I have the following query which gives me the right results. But it's super slow.
What makes it slow is the
AND a.id IN (SELECT id FROM st_address GROUP BY element_id)
part. The query should show from which countries we get how many orders.
A person can have multiple addresses, but in this case, we only only want one.
Cause otherwise it will count the order multiple times. Maybe there is a better way to achieve this? A distinct join on the person or something?
SELECT cou.title_en, COUNT(co.id), SUM(co.price) AS amount
FROM customer_order co
JOIN st_person p ON (co.person_id = p.id)
JOIN st_address a ON (co.person_id = a.element_id AND a.element_type_id = 1)
JOIN st_country cou ON (a.country_id = cou.id)
WHERE order_status_id != 7 AND a.id IN (SELECT id FROM st_address GROUP BY element_id)
GROUP BY cou.id
Have you tried to replace the IN with an EXISTS?
AND EXISTS (SELECT 1 FROM st_address b WHERE a.id = b.id)
The EXISTS part should stop the subquery as soon as the first row matching the condition is found. I have read conflicting comments on if this is actually happening though so you might throw a limit 1 in there to see if you get any gain.
I found a faster solution. The trick is a join with a sub query:
JOIN (SELECT element_id, country_id, id FROM st_address WHERE element_type_id = 1 GROUP BY
This is the complete query:
SELECT cou.title_en, COUNT(o.id), SUM(o.price) AS amount
FROM customer_order o
JOIN (SELECT element_id, country_id, id FROM st_address WHERE element_type_id = 1 GROUP BY element_id) AS a ON (o.person_id = a.element_id)
JOIN st_country cou ON (a.country_id = cou.id)
WHERE o.order_status_id != 7
GROUP BY cou.id