Count multiple columns with Group By and Union All? - mysql

I have a query where I want to count the values of 3 columns s, s2 and s3 and use Group By the values of column s?
So far i have made this db-fiddle
This will give me the output
1 - count 3
2 - count 3
4 - count 4
This is almost correct but I also want to include the Where clause correct so the count will only be where season = '2018/2019' and round = 34.
The wanted output must be:
1 - count 3
2 - count 2
4 - count 2
Any idea how to edit this query so the Where clause will work in the counted values?
Kinds regards,
Arie

You have to expand the unioned queries to include season and round and add conditions in the where clause:
SELECT t.s, COUNT(*) as count FROM (
SELECT s, season, round FROM tablename UNION all
SELECT s2, season, round FROM tablename UNION all
SELECT s3, season, round FROM tablename
) as t
WHERE
t.s IN (
SELECT s FROM tablename
WHERE season = '2018/2019'
AND round = 34
AND s is not null
)
AND t.season = '2018/2019'
AND t.round = 34
AND t.s is not null
GROUP BY t.s
ORDER BY count DESC, t.s
See the demo.
Results:
| s | count |
| --- | ----- |
| 1 | 3 |
| 2 | 2 |
| 4 | 2 |

You should filter the rows for each table in union
SELECT t.s, COUNT(*) as count FROM (
SELECT s
FROM tablename
WHERE season = '2018/2019' and round = 34
UNION all
SELECT s2
FROM tablename
WHERE season = '2018/2019' and round = 34
UNION all
SELECT s3
FROM tablename
WHERE season = '2018/2019' and round = 34
) as t
GROUP BY t.s
ORDER BY count DESC

Related

Count rows which are more than once and twice by one query

I have a table similar to: (There are actually many more rows.)
user_id | text
---------------------------
1 | a
1 | b
2 | c
3 | d
3 | e
4 | f
4 | g
4 | h
4 | i
5 | j
5 | k
5 | l
6 | m
I want to know how many users appeared more than once, and how many users appeared more than twice among them.((4, 2) for above table)
Now I'm using this query, but I have to run it two times after changing the number to 2.
SELECT COUNT(*)
FROM (
SELECT NULL
FROM my_table
GROUP BY user_id
HAVING COUNT(*) > 1
) T1
Because table is so big, it takes a lot of time. Can I handle these two cases in one Query?
You can do that in one query by summing the counts:
SELECT SUM(count > 1) AS more_than_once,
SUM(count > 2) AS more_than_twice
FROM (SELECT COUNT(*) AS count
FROM my_table
GROUP BY user_id
HAVING count > 1) t
Output:
more_than_once more_than_twice
4 2
Demo on dbfiddle
try like this mate
SELECT COUNT(*)
FROM (
SELECT NULL
FROM my_table
GROUP BY user_id
HAVING COUNT(*) > 1
) T1 WHERE COUNT(*) > 2
SELECT SUM(v.gt1) AS cnt_gt_1
, SUM(v.eq3) AS cnt_eq_2
, SUM(v.gt2) AS cnt_gt_2
FROM ( SELECT COUNT(*) > 1 AS gt1
, COUNT(*) = 2 AS eq2
, COUNT(*) > 2 AS gt2
FROM mytable t
GROUP
BY t.user_id
HAVING COUNT(*) > 1
) v
For performance of the inline view query, we want an index with user_id as the leading column... e.g.
... ON my_table (user_id)

Group all rows after nth row together

I have the current table:
+----------+-------+
| salesman | sales |
+----------+-------+
| 1 | 142 |
| 2 | 120 |
| 3 | 176 |
| 4 | 140 |
| 5 | 113 |
| 6 | 137 |
| 7 | 152 |
+----------+-------+
I would like to make a query to retrieve the 3 top salesman, and an "Other" column, that would be the sum of everyone else. The expected output would be:
+----------+-------+
| salesman | sales |
+----------+-------+
| 3 | 176 |
| 7 | 152 |
| 1 | 142 |
| Others | 510 |
+----------+-------+
I am using MySQL, and I am experienced about it, but i can't imagine a way of doing this kind of GROUP BY.
A tried UNION with 2 SELECT, one for the top 3 salesman and another select for the "Others", but I couldn't figure a way of excluding the top 3 from the 2nd SELECT
You can do this by LEFT JOINing your table to a list of the top 3 salesmen, and then grouping on the COALESCEd salesman number from the top 3 table (which will be NULL if the salesman is not in the top 3).
SELECT COALESCE(top.sman, 'Others') AS saleman,
SUM(sales) AS sales
FROM test
LEFT JOIN (SELECT salesman AS sman
FROM test
ORDER BY sales DESC
LIMIT 3) top ON top.sman = test.salesman
GROUP BY saleman
ORDER BY saleman = 'Others', sales DESC
Output:
saleman sales
3 176
7 152
1 142
Others 510
Demo on dbfiddle
Using UNION, ORDER BY, LIMIT, OFFSET AND GROUP BY statements you should do the trick:
SELECT salesman, sales
FROM t
ORDER BY sales DESC LIMIT 3
UNION
SELECT 'Others', SUM(sales)
FROM (SELECT salesman, sales
FROM t
ORDER BY sales DESC LIMIT 3, 18446744073709551615) AS tt;
The big number at the end is the way to apply limit until the end of the table, as suggested here
This is a pain in MySQL:
(select salesman, count(*) as cnt
from t
group by salesman
order by count(*), salesman
limit 3
) union all
(select 'Others', count(*)
from t left join
(select salesman, count(*) as cnt
from t
group by salesman
order by count(*)
limit 3
) t3
on t3.salesman = t.salesman
where t3.salesman is null
);
This should be the fastest one if appropriate indexes are present:
(
SELECT salesman, sales
FROM t
ORDER BY sales DESC
LIMIT 3
)
UNION ALL
(
SELECT 'Other', SUM(sales) - (
SELECT SUM(sales)
FROM (
SELECT sales
FROM t
ORDER BY sales DESC
LIMIT 3
) AS top3
)
FROM t
)
ORDER BY CASE WHEN salesman = 'Other' THEN NULL ELSE sales END DESC
this will work:
select salesman,sales from tablename a where a.salesman in (3,7,1)
union all
select 'others' as others,sum(a.sales) as sum_of_others from tablename a where
a.salesman not in (3,7,1) group by others;
check https://www.db-fiddle.com/f/73GjFXL3KsZsYnN26g3rS2/0

Get latest record from each group and number of group rows in MySQL

I got a table like this:
id | column_a | column_value
1 | x | 5
2 | y | 7
3 | z | 4,7
4 | x | 3,6
5 | y | 2
6 | w | 5,8,9,11
I would like to get back column_value from latest record in each groups AND a count number of rows in the groups.
So the result should be this:
count(id) | column_value
2 | 3,6
2 | 2
1 | 4,7
1 | 5,8,9,11
I tried to reach this on the following two path:
select count(id), column_value
from table
group by column_a
This version get back the first records from the groups so its not ok for me.
select count(id), column_value
from table
where id in (select max(id)
from table
group by column_a)
This version also wrong because count cannot works well without group by.
I cannot figure it out how can I combine two versions advantages.
Any help is appreciated.
Try this
Select cnt, column_value
from tst t inner join (
Select column_a, count(id) cnt, max(id) as max_id
from tst
group by column_a ) x on (t.column_a= x.column_a and t.id = x.max_id)
order by cnt desc

Count distinct values where count of another value = 1

Given
------------------------------
|id | val1 | val2 | date |
______________________________
1 10 2 1990-10-02
2 10 3 1990-10-02
3 1 1 1990-10-02
4 21 1 1990-10-02
5 30 3 1990-10-02
6 30 1 1990-10-02
I want to have in results the row with id 3 and 4 because they have only one val1 if we group by val1.
How to achieve this?
SELECT DISTINCT COUNT(*) WHERE
You can use group by and having for this:
select t.*
from t
group by val1
having count(*) = 1;
In general, I am opposed to having an aggregation query with unaggregated columns in the select. However, it is fine in this case because the count(*) guarantees that there is only one matching row.
Note: this will not work in other databases.
SELECT DISTINCT x.*
FROM my_table x
LEFT
JOIN my_table y
ON y.id <> x.id AND y.val1 = x.val2
WHERE y.id IS NULL;

MySQL Multiple COUNT() with different conditions in single QUERY

I have a table with the following structure
id | season
1 | 1
2 | 1
2 | 2
3 | 2
4 | 2
5 | 1
I want the query to return the count of the the total IDs like:
total_season2 | new | existing
3 | 2 | 1
I can do it with multiple Queries or using php but I want to have the results in a single query
Since you don't need to select all the rows you can use an empty select with subqueries to get the data you want. There may be more efficient ways to getting the same data, but this will work:
SELECT
(SELECT COUNT(id) FROM seasons s WHERE s.season = 2) as total_season2,
(SELECT COUNT(id) FROM seasons s WHERE s.season = 2 AND (SELECT distinct COUNT(ss.id) FROM seasons ss WHERE ss.id = s.id) = 1) as new,
(SELECT COUNT(id) FROM seasons s WHERE s.season = 2 AND (SELECT distinct COUNT(ss.id) FROM seasons ss WHERE ss.id = s.id) > 1) as existing