SQL max value form count() - mysql

I've got a following query:
SELECT BusID, count(BusID) as 'NoofConnections'
FROM mytable
Group By BusID
Order by BusID
And I get following table:
BusID NoofConnections
=========================
1 6
2 6
4 3
5 2
3 1
And I will to select just maximum from NoofConnections, so in this case LIMIT 1 doesn't work, so we have two equal values. Like this:
BusID NoofConnections
=========================
1 6
2 6
Any ideeas?

You can use a subquery:
SELECT BusID, COUNT(*) as NoofConnections
FROM mytable
GROUP BY BusID
HAVING COUNT(*) = (SELECT COUNT(*)
FROM mytable
GROUP BY BusID
ORDER BY COUNT(*) DESC
LIMIT 1
)
ORDER BY BusID;

You could use a subselect
select * from (
SELECT BusID, count(BusID) as NoofConnections
FROM mytable
Group By BusID
) t1
where t1.NoofConnections = ( select max(NoofConnections)
from (
SELECT BusID, count(BusID) as NoofConnections
FROM mytable
Group By BusID
)

Related

Find the most frequent value in mysql,display all in case of a tie

For example, we have 1, 2 and 3 are the most frequent values at the same time, how to return them when it is a tie?
id
1
1
1
2
2
2
3
3
3
4
You could try:
SELECT id
FROM yourTable
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*) FROM yourTable
GROUP BY id ORDER BY COUNT(*) DESC LIMIT 1);
On more recent versions of MySQL 8+, we can use RANK here:
WITH cte AS (
SELECT id, RANK() OVER (ORDER BY COUNT(*) DESC) rnk
FROM yourTable
GROUP BY id
)
SELECT id
FROM cte
WHERE rnk = 1;

Distinct 2 Different Columns, How to print total combination in every row

Having this query,
SELECT DISTINCT ID, DATE FROM MAIN_TAB ORDER BY ID ASC
How can I print the total of different combinations for ID field, on the front of every row, example TOTAL_DISTINCT_VALUES:
ID DATE TOTAL_DISTINCT_VALUES
37870 02/07/2018 3
37870 03/07/2018 3
37870 04/07/2018 3
55887 04/07/2018 2
55887 03/07/2018 2
61891 02/07/2018 1
44891 02/07/2018 1
75891 02/07/2018 1
You could use count and group by
SELECT ID, DATE, count(*) TOTAL_DISINCT_VALUE
FROM MAIN_TAB
GROUP BY ID, DATE
ORDER BY ID ASC
but looking to you data sample seems you need cont only for id so you could use a join on the count group by id
select t.id, a.date, t.TOTAL_DISTINCT_VALUE
from MAIN_TAB a
inner JOIN (
select id, count(*) TOTAL_DISTINCT_VALUE
FROM MAIN_TAB
group by ID
) t on a.id = t.id
or as suggested by barmar . count(distinct date)
select t.id, a.date, t.TOTAL_DISTINCT_VALUE
from MAIN_TAB a
inner JOIN (
select id, count(distinct date) TOTAL_DISTINCT_VALUE
FROM MAIN_TAB
group by ID
) t on a.id = t.id
use group by clause
SELECT ID, DATE,count(*) as distinct_value FROM MAIN_TAB
group by ID, DATE
ORDER BY ID ASC
Try this:
select ID,DATE,count(*) as TOTAL_DISINCT_VALUE from MAIN_TAB group by ID,DATE order by ID asc;
and replace * with any other column name except ID and DATE.

Select the last price according to the date using GROUP BY

I'm trying to do a request with a group BY.
Here is an exemple of my table ticket :
id DtSell Price Qt
1 01-01-2017 3.00 1
1 02-01-2017 2.00 3
2 01-01-2017 5.00 5
2 02-01-2017 8.00 2
And my request :
SELECT id, Price, sum(Qt) FROM ticket
GROUP BY id;
but unfortunately, the price returned is not necessarily the right one; I would like to have the last price according to DtSell like that :
id Price sum(Qt)
1 2.00 4
2 8.00 7
But i didn't find how to do it.
Can you help me ?
Thank you in advance!!
You might need a sub query,try below:
SELECT
t1.id,
(SELECT t2.price FROM ticket t2 WHERE t2.id=t1.id
ORDER BY t2.DtSell DESC LIMIT 1 ) AS price,
SUM(t1.Qt)
FROM ticket t1 GROUP BY t1.id;
You can do this with a group_concat()/substring_index() trick:
SELECT id, Price, SUM(Qt)
SUBSTRING_INDEX(GROUP_CONCAT(price ORDER BY dtsell DESC), ',' 1) as last_price
FROM ticket
GROUP BY id;
Two notes:
This is subject to internal limits on the length of the intermediate string used for GROUP_CONAT() (a limit that can easily be changed).
It changes the type of price to a string.
Try this query.
SELECT id, Price, sum(Qt) FROM ticket
GROUP BY id,Price
Your Output;
id Price sum(Qt)
1 3.00 4
2 8.00 7
You can select all rows from ticket grouped by id ( to sum quantity), then join to the rows which have the max dtsell for each id group( to select the price).
http://sqlfiddle.com/#!9/574cb9/8
SELECT t.id
, t3.price
, SUM(t.Qt)
FROM ticket t
JOIN ( SELECT t1.id
, t1.price
FROM ticket t1
JOIN ( SELECT id
, MAX(dtsell) dtsell
FROM ticket
GROUP BY id ) t2
ON t1.id = t2.id
AND t1.dtsell = t2.dtsell ) t3
ON t3.id = t.id
GROUP BY t.id;
You can do it like this:
declare #t table (id int, dtsell date, price numeric(18,2),qt int)
insert into #t
values
(1 ,'01-01-2017', 3.00 , 1),
(1 ,'02-01-2017', 2.00 , 3),
(2 ,'01-01-2017', 5.00 , 5),
(2 ,'02-01-2017', 8.00 , 2)
select x.id,price,z.Qt from (
select id,price,dtsell,row_number() over(partition by id order by dtsell desc ) as rn from #t
)x
inner join (select SUM(qt) as Qt,ID from #t group by id ) z on x.id = z.id
where rn = 1

MySQL query to exclude highest and lowest count

I have following table in MySql
Number
1
2
3
2
3
4
4
4
I would like to get numbers by count but with excluded highest and lowest count. This should be the result
Number Count
2 2
3 2
Please help me with this query.
Try this:
SELECT number, COUNT(*) cnt
FROM mytable
GROUP BY number
HAVING cnt <> (SELECT COUNT(*)
FROM mytable
GROUP BY number
ORDER BY COUNT(*) LIMIT 1)
AND
cnt <> (SELECT COUNT(*)
FROM mytable
GROUP BY number
ORDER BY COUNT(*) DESC LIMIT 1)
The two subqueries used in the HAVING clause return the minimum and maximum count. Hence the two predicates of the HAVING clause filter out the groups with the highest and lowest count.
A solution is using user variable and sub-query.
Query needed:
select Number, Count
from (
select Number, count(*) as Count, #rank := #rank+1 as rank
from t1 cross join (select #rank := 0) param
group by Number
order by Count ) t2
where rank not in (1, #rank);
Demo:
create table t1(Number int);
insert into t1 values(1),(2),(3),(2),(3),(4),(4),(4);
select Number, Count
from (
select Number, count(*) as Count, #rank := #rank+1 as rank
from t1 cross join (select #rank := 0) param
group by Number
order by Count ) t2
where rank not in (1, #rank);
Output:
mysql> select Number, Count
-> from (
-> select Number, count(*) as Count, #rank := #rank+1 as rank
-> from t1 cross join (select #rank := 0) param
-> group by Number
-> order by Count ) t2
-> where rank not in (1, #rank);
+--------+-------+
| Number | Count |
+--------+-------+
| 2 | 2 |
| 3 | 2 |
+--------+-------+
2 rows in set (0.00 sec)
select number,count(number)
from numbers
where number not in ((select max(number) from numbers),(select min(number) from numbers) )
group by number
sqlfiddle demo
First select all rows except the maximum and minimum numbers.
Then find the count(number) from the result set.
Query
select t.number, count(t.number) as `Count` from(
select * from your_table_name
where number not in (
select max(number) from your_table_name
)
and number not in (
select min(number) from your_table_name
)
)t
group by t.num;
SELECT column FROM tbl
LIMIT 10 OFFSET 20
SELECT MIN(taka) AS mintaka, MAX(taka) AS maxtaka
FROM (SELECT taka FROM tbl LIMIT 10 OFFSET 20);

MySQL: select 5 rows before and after specific row

I have table called "users" and need to select 2 rows before and after specific row, sorted by users.score ASC
users table (structure):
id name score
1 John 2
2 Sara 1
3 san 3
4 test 2
5 jery 5
6 simon 6
7 bob2 7
8 jack 4
9 man 2
for example: need to select 2 rows before and after users.id = 5 order by users.score
result should be like:
id name score
3 san 3
8 jack 4
5 jery 5
6 simon 6
7 bob2 7
thanks,
Using union all and subqueries to limit the records should do it:
select * from users where id = 5
union all (
select * from users
where score < (select score from users where id = 5)
order by score desc limit 2
)
union all (
select * from users
where score > (select score from users where id = 5)
order by score asc limit 2
)
order by score
Sample SQL Fiddle
Edit: I think a better method is to number the rows according to score and then select the rows with number -2 and +2 from the rows of id 5:
select id, name, score
from (select
t.*, #rownum1 := #rownum1 + 1 as rank
from users t, (select #rownum1 := 0) r
order by score
) a,
(select rank from (
select t.*,
#rownum := #rownum + 1 as rank
from users t, (select #rownum := 0) r
order by score
) t
where id = 5
) b
where b.rank between a.rank -2 and a.rank+2
order by score;
Sample SQL Fiddle
Perhaps using union all
(
select * from users where id < 5 order by score limit 2
)
union all
(
select * from users where id > 5 order by score limit 2
)
(SELECT x.* FROM users x JOIN users y ON y.score <= x. score WHERE y.id = 5 ORDER BY score LIMIT 3)
UNION
(SELECT x.* FROM users x JOIN users y ON y.score >= x. score WHERE y.id = 5 ORDER BY score DESc LIMIT 3)
[ORDER BY score] ;
http://www.sqlfiddle.com/#!9/45c22/42
I just write the query, based on "jpw" solution (many thanks to him)
select * from users where id = 5
union all (
select * from users
where id in (select id from users where score < (select score from users u where u.id = 5) order by score ASC)
order by score desc limit 2
)
union all (
select * from users
where id in (select id from users where score > (select score from users u where u.id = 5) order by score ASC)
order by score ASC limit 2
)
order by score
Selecting arbitrarily ordered rows before and after a specific id
SET #j = 0;
SET #i = 0;
SELECT *
FROM (
SELECT id, col1, col2, ..., #j:=#j+1 AS pos
FROM `table`
WHERE col1=... ORDER BY col1 DESC, col2 ASC
) AS zz
WHERE (
SELECT position
FROM (
SELECT id AS id2, #i:=#i+1 AS position
FROM `table`
WHERE col1=... ORDER BY col1 DESC, col2 ASC
) AS zz
WHERE id2=$currId
)
IN (pos-5,pos-4,pos-3,pos-2,pos-1,pos,pos+1,pos+2,pos+3,pos+4,pos+5)