Multiple Aggregate with different Group By - mysql

I have table User, Company, ParentCompany and table Goal.
Each Company have ParentCompany, and each User inside one Company. Goal have number of action, and type of Goal, user who execute the goal, and time executed.
I want to calculate the number of action in a date range for each type of Goal, for each user, company, and parent_company. Number of action for each company equal to sum of action for user that reside in that company.
More or less after some join query, I able to get this table below, where column id is id of company, parent_id is id of companyparent, and num is number of goal for all user inside of id company.
id parent_id num
----------- -------------------- -----------------------
1 3 1
2 1 2
3 1 1
4 2 4
Now I want to make it like below:
id parent_id sum_id sum_parent
----------- -------------------- -------------- -------------
1 3 1 1
2 1 2 3
3 1 1 3
4 2 4 4
How can I make it works? I can get one of the value (sum_id or sum_parent) with GROUP BY,
SELECT id,SUM(num) AS sum_id FROM tableA GROUP BY id
or
SELECT parent_id,SUM(num) AS sum_parent FROM tableA GROUP BY parent_id
but is there any way to make it only in one query? tableA results from query with 5 join inside.

Try this:
SELECT a.id, a.parent_id, a.sum_id, b.sum_parent
FROM (SELECT id, parent_id, SUM(num) sum_id FROM tableA a GROUP BY id) a
INNER JOIN (SELECT parent_id, SUM(num) sum_parent FROM tableA a GROUP BY parent_id) b ON a.parent_id = b.parent_id

Try this :
SELECT
t1.id, t1.parent_id, t1.sum_id, t2.sum_parent
FROM
(SELECT id, parent_id, SUM(num) AS sum_id FROM mytable GROUP BY id) t1
INNER JOIN
(SELECT parent_id, SUM(num) AS sum_parent FROM mytable GROUP BY parent_id) t2
ON t1.parent_id = t2.parent_id

Apparently what I want can be done with WITH ROLLUP statement. (http://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html)
With
SELECT id,sum(num) FROM tableA GROUP BY parent_id, id WITH ROLLUP;
will results in
parent_id id sum(num)
----------- -------------------- --------------
1 2 2
1 3 1
1 null 3
2 4 4
2 null 4
3 1 2
3 null 2

Related

SQL query to only yield multiple occurances

I am using mariadb and I have a table called links:
id | product_id | last_change
------------------------------
1 1 xxx
2 2 xxx
3 5 xxx
4 5 xxx
I want to find every object (3, 4 in this example) that occures more than once. Following this answer I tried:
SELECT product_id, COUNT(*) from links HAVING COUNT(*) > 1
But this results in the (adapted to this example) first row being shown and the total number of product_id occurrences:
product_id | COUNT(*)
---------------------
1 4
I wanted to achieve a list of all items occuring more than once:
id | product_id | last_change
------------------------------
3 5 xxx
4 5 xxx
An aggregation function without GROUP BY always results in only one row result as it aggregates all rows
So use a GROUP BY
SELECT product_id, COUNT(*) from links GROUP BY product_id HAVING COUNT(*) > 1
To see all entry with the count of the product_id , you can do following
SELECT l1.product_id , last_change , Count_
FROM links l1
JOIN (SELECT product_id, COUNT(*) as Count_ from links GROUP BY product_id HAVING COUNT(*) > 1) l2
ON l1.product_id = l2.product_id
Try below statement
select id, product_id, count(product_id)
from links
group by (product_id)
having count(product_id)> 1;

mysql count children of selected rows having selected rows as parent?

Table structure(representative)
ID NAME PARENT
--------------------
1 cat1 0
2 cat1 1
3 cat2 1
4 cat1 2
5 cat2 2
6 cat3 2
7 cat1 3
8 cat2 3
9 cat3 3
10 cat1 1
FOREIGN TABLE data for foreign_sub_category_count
id_parent name
-----------------------
2 a
2 b
2 c
3 a
3 b
3 c
categories may have sub categories.
SELECT t.name,t.id
FROM TABLE_NAME AS t
WHERE t.parent = SOME_ID
SOME_ID = 1
gives me the name,id of all categories with SOME_ID parent id
what i want is to get a count of all sub categories of each row in above result set besides the name
WHERE t.id is parent of sub categories and get count of categories from another table which has the same t.id as parent
EXPECTED RESULT
t.id t.name sub_category_count foreign_sub_category_count
2 cat1 3 3
3 cat2 3 3
10 cat1 0 0
I suspect that you are looking for a recursive query - available in MySQL 8.0:
with recursive cte as (
select id root_id, id from mytable
union all
select c.root_id, t.id from cte c inner join mytable t on t.parent = c.id
)
select
t.*,
(select count(*) - 1 from cte c where c.root_id = t.id) no_children
from mytable t
This adds one column to your original table, which contains the number of direct and indirect descendants of the current row.
Try this:
select
tab1.id,
tab1.name,
coalesce(tab2.counts,0) as sub_category_count,
coalesce(tab3.counts,0) as foreign_sub_category_count
from
(select id,name,parent from representative) tab1
left join
(select t1.parent tab_id, count(*) as counts from representative t1 inner join representative t2 on t1.parent=t2.id group by t1.parent) tab2
on tab1.id=tab2.tab_id
left join
(select parent_id,count(*) as counts from foreign_table group by parent_id) tab3
on tab1.id=tab3.parent_id
where tab1.parent=1 --SOME_ID
you can change the parent_id in where tab1.parent=1 of you choice
Example on DB-FIDDLE

Select ONLY one row per category

Ok I have siple table which contains data:
id cat_id title (with random values)
1 1 test
2 1 tstt
3 3 tewt
4 2 4324
5 3 rterter
Now, I need to create a query which selects only ONE raw per category (cat_id)
(possibly with lowest ID and ordered by cat_id)
So the result should be:
1 1 test
4 2 4324
3 3 tewt
Use GROUP BY :
SELECT MIN(id), cat_id, title FROM table GROUP BY cat_id
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT cat_id, MIN(id) id
FROM tableName
GROUP BY cat_id
) b ON a.cat_id = b.cat_id AND
a.id = b.id
ORDER BY a.cat_id

Counting unique numbers in a column MySQL

I have a query that returns data in the following format:
id | name | number
1 John 12545
1 John 50496
2 Mary 23443
3 Mark 54
3 Mark 5600
3 Mark 50206
I would like to find out the number of distinct ids that appear in the result set. For example, for the result above. I would like to obtain the value 3.
Is there any way to add a column so the result looks like this instead?
count | id | name | number
3 1 John 12545
3 1 John 50496
3 2 Mary 23443
3 3 Mark 54
3 3 Mark 5600
3 3 Mark 50206
My query is:
SELECT * FROM (
SELECT id FROM tableA
WHERE xyz
) as t1
JOIN tableB using (id)
SELECT (SELECT COUNT(DISTINCT id) FROM tableName) totalCount,
id,name,number
FROM tableName
or by using CROSS JOIN
SELECT x.totalCount,
a.id, a.name, a.number
FROM tableName a, (SELECT COUNT(DISTINCT id) totalCount
FROM tableName) x
You should try :
SELECT id,name,number, (SELECT COUNT(DISTINCT name) FROM YourTableName) FROM YourTableName
Good luck
SELECT COUNT(DISTINCT id) would be faster than using column name.
SELECT (SELECT COUNT(DISTINCT id) FROM tableName) as 'count',
id,name,number
FROM tableName
SELECT COUNT(id) AS count , id, name, number
FROM
(
SELECT id
FROM tableA
WHERE xyz
) as t1
JOIN tableB using (id)
GROUP BY id, name, number

SQL count each distinct value in column and add name from another table where the ID matches

My SQL Skills are next to none. After looking around for the past 2 hours trying to figure this out I need some help please.
I have 2 tables as below
Table1 Table2
ID | Name Status_id
----------- ----------
1 | Open 1
2 | Closed 2
3 | On-Hold 1
What I would like to do is count the status_id in table 2 and group by the status_id. Then add the Name where the ID matches in the first column.
What I have at the moment is
SELECT status_id, COUNT(*) AS 'num' FROM table2 GROUP BY status_id
This is great so far and returns
1 | 2
2 | 1
What I need to return is
Open | 2
Closed | 1
I hope that is clear. Can anyone help?
Many thanks!
SELECT a.name, COUNT(*) AS num FROM table2 b
INNER JOIN table1 a
ON b.status_id=a.id
GROUP BY status_id
In the case that you want to also have Zero for On-Hold you'd need to do a LEFT join and count the a column from table2 instead of *
SELECT t1.name,
Count(t2.Status_id) AS num
FROM table1 t1
LEFT JOIN table2 t2
ON t1.id = t2.Status_id
GROUP BY t1.name;
DEMO