how to find maximum if i have more than one answer - mysql

I have a table:
ID CLUSTERID
1 56
1 24
1 24
1 35
2 13
2 24
Now, i want to get the following:
I want to count per id, which cluster id repeats most of the time.
For example, in ID=1, CLUSTERID=24 repeats most of the time
In ID=2 i have 2 CLUSTER IDs that repeats the same.
So in the output i will have:
ID CLUSTERID
1 24
2 13
2 24
The answer that i wrote (and works)
TT is my original table that have 2 columns: ID and CLUSTER ID
SELECT t3.ID,t3.ClusterID,t3.ListingAmount
FROM
(SELECT ID, ClusterID, COUNT() AS ListingAmount
FROM tt
GROUP BY ID, ClusterID) AS t3 LEFT JOIN
(SELECT ID, MAX(ListingAmount) AS amount
FROM
(SELECT ID, ClusterID, COUNT() AS ListingAmount
FROM tt
GROUP BY ID, ClusterID) AS t2
GROUP BY ID) AS BB ON BB.id=t3.id
WHERE BB.amount=t3.ListingAmount

Can't think of a more elegant solution right now (I'm sure there is), but it seems to do the job:
select t1.id,
t1.clusterid,
t1.cnt
from (
select id,
clusterid,
count(*) as cnt
from foo
group by id, clusterid
) t1
join (select id,
max(cnt) as max_count
from (
select id,
clusterid,
count(*) as cnt
from foo
group by id, clusterid
) tm
group by id
) t2 on t1.id = t2.id
and t1.cnt = t2.max_count
order by t1.id, t1.cnt;
SQLFiddle example: http://sqlfiddle.com/#!2/2cacc/3

Related

SQL Query to find records belongs to two states

cust_id
state
1
CA
2
IL
3
SC
1
PA
3
IA
4
MO
5
VA
4
NY
Can any one please advise on SQL Query that return the cust_id that belong to two states as below:
The output should be
cust_id
state
1
CA
1
PA
3
SC
3
IA
4
NY
4
MO
Try the following query
Solution 1
Select * From yourtable
Where Cust_Id In (Select cust_id From yourtable Group By cust_id Having
Count(*) = 2) Order By cust_id,state
Solution 2
With T1 As
(Select cust_id From yourtable Group By cust_id Having Count(*) = 2)
Select T2.* From yourtable T2 Join T1 On T1.cust_id = T2.cust_id O
Order By T2.cust_id,T2.state
SELECT tmp.*
FROM tmp
INNER JOIN (
SELECT cust_id
,COUNT(STATE) s_count
FROM tmp
GROUP BY [cust_id]
) sub
ON tmp.cust_id = sub.cust_id
WHERE sub.s_count = 2
ORDER BY cust_id
,STATE
One simple approach would use a COUNT window function, that will assign the amount of times each "cust_id" occurs in your table. Once you get this value, you can filter out rows whose count is smaller than 2.
WITH cte AS (
SELECT *, COUNT(cust_id) OVER(PARTITION BY cust_id) AS cnt
FROM tab
)
SELECT cust_id,
state
FROM cte
WHERE cnt > 1
Check the demo here.

How to write a simple self join query to find result by comparing it self?

Let me being honest, I am Java developer assigned with this SQL development work where I need to list out all the orderId which having nodeName 'Delay' and id is 'MAX(id)'
id
orderId
nodeName
1
2
Rain
2
2
Summer
3
2
Delay
4
2
Winter
5
5
Rain
6
5
Delay
7
5
Summer
8
5
Winter
9
3
Rain
10
3
Summer
11
3
Delay
12
1
Rain
13
1
Delay
14
1
Summer
15
1
Delay
In above example it should fetch orderId 3 and 1 and ignore rest of the all orderId.
I know few might think it's a silly question but I have not much experience on SQL queries so I raised it on this forum.
Use a correlated subquery to check if the last id of each orderId has nodeName = 'Delay':
SELECT DISTINCT t1.orderId
FROM tablename t1
WHERE t1.nodeName = 'Delay'
AND t1.id = (SELECT MAX(t2.id) FROM tablename t2 WHERE t2.orderId = t1.orderId)
Or:
SELECT DISTINCT t1.orderId
FROM tablename t1
WHERE 'Delay' = (
SELECT t2.nodeName
FROM tablename t2
WHERE t2.orderId = t1.orderId
ORDER BY id DESC LIMIT 1
)
Or, with ROW_NUMBER() window function:
SELECT orderId
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY orderId ORDER BY id DESC) rn
FROM tablename
) t
WHERE rn = 1 AND nodeName = 'Delay'
See the demo.
I need to list out all the orderId which having nodeName 'Delay' and id is 'MAX(id)'
One approach is aggregation with a having clause:
select orderid
from t
group by orderid
having max(id) = max(case when nodename = 'Delay' then id end);
Or, if you do use a correlated subquery, not exists comes to mind:
select orderid
from t
where t.nodename = 'Delay' and
not exists (select 1
from t t2
where t2.orderid = t.orderid and
t2.nodename <> 'Delay' and
t2.id > t.id
);
Assuming you are searching for only one row,
try:
SELECT MAX(id), orderId, nodeName
FROM table_name
WHERE nodeName = 'Delay';
If you are not searching for only one row, but for the results with the highest id,
Try:
SELECT *
FROM table_name
WHERE nodeName = 'Delay'
ORDER BY id DESC
LIMIT 5;
you can use following query
select t1.orderId
from tablename t1
join (SELECT MAX(id) as id FROM tablename group by orderId) t2 on t1.id = t2.id
where t1.nodeName = 'Delay'

How to get previous last row in MySQL

I have below mentioned two tables.
Table1
ID ref_id
O-1 rt-1-r
O-2 rx-2-e
Table2
ref_id seq value
rt-1-r 1 10
rt-1-r 2 15
rt-1-r 3 0
rt-1-r 4 18
rx-2-e 12 1
rx-2-e 13 13
rx-2-e 14 21
Required Output
ID Value
O-1 0
O-2 13
I have tried below mentioned query but it is working for one ID when I pass multiple ID in IN it is not working.
select b.ID, a.Value
FROM Table2 a
LEFT JOIN Table1 b ON a.ref_id = b.ref_id
WHERE a.ID IN ('O-1')
order by a.seq desc limit 1 OFFSET 1;
I would use ROW_NUMBER here:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY ref_id ORDER BY seq DESC) rn
FROM Table2
)
SELECT t1.ID, t2.value
FROM Table1 t1
INNER JOIN cte t2
ON t2.ref_id = t1.ref_id
WHERE t2.rn = 2;
I don't like not using analytic functions for this, but if you had to here is one way:
SELECT
t1.ID,
(SELECT value FROM Table2 t2
WHERE t2.ref_id = t1.ref_id AND
t2.seq < (SELECT MAX(s.seq) FROM Table2 s WHERE s.ref_id = t2.ref_id)
ORDER BY t2.seq DESC LIMIT 1) AS value
FROM Table1 t1;

Select all orders except the max order for each distinct customer

Sorry for the poor formatting but as part of a larger problem, I have created a query that produces this table:
id id2
4 7
4 6
1 3
1 2
1 1
How would I extract the rows that don't have the highest id2 for each id1.
What I want:
id id2
4 6
1 2
1 1
I can only seem to figure out how to get rid of the max id2 overall but not for each distinct id1. Any help on actually differentiating the max id2 for each id1 would be appreciated.
You can try below way -
select a.id, a.id2
from tablename a
where a.id2 <> (select max(a1.id2) from tablename a1 where a.id=a1.id)
If you are using MySQL 8+, then RANK() provides one option:
WITH cte AS (
SELECT id, id2, RANK() OVER (PARTITION BY id ORDER BY id2 DESC) rnk
FROM yourTable
)
SELECT id, id2
FROM cte
WHERE rnk > 1
ORDER BY id DESC, id2 DESC;
Demo
instead of a correlated subquery in the where, you can LEFT JOIN and apply not in...
select id, id2
from yourTable YT
LEFT JOIN
( select id, max( id2 ) highestID2
from YourTable
group by id ) TopPerID
on YT.ID = TopPerID.ID
AND YT.ID2 != TopPerID.highestID2
where TopPerID.id IS NULL
Since you can have id values with only one id2 value, you need to check for that situation as well, which you can do by comparing the MAX(id2) value with the MIN(id2) value in a JOIN:
SELECT t1.*
FROM Table1 t1
JOIN (SELECT id, MAX(id2) AS max_id2, MIN(id2) AS min_id2
FROM Table1
GROUP BY id) t2 ON t2.id = t1.id
AND (t1.id2 < t2.max_id2 OR t2.min_id2 = t2.max_id2)
If we add a row 2, 5 to your sample data this correctly gives the result as
id id2
4 6
1 2
1 1
2 5
Demo on SQLFiddle

How to solve this particular query?

SELECT id, count(*) as Number
FROM (SELECT id FROM t1
UNION ALL
SELECT id FROM t2
UNION ALL
SELECT id FROM t3
) t
GROUP BY id
ORDER BY Number DESC
This is the query giving me the correct result. But When I want to add where call it is throwing error.
SELECT id, count(*) as Number
FROM (SELECT id from t1
UNION ALL
select id from t2
UNION ALL
select id from t3
) t
WHERE Number > 10
GROUP BY id
ORDER BY Number DESC
You want to test conditions on an aggregate function with a HAVING clause rather than a WHERE.
select id, count(*) as Number
from (select id
from t1
UNION ALL
select id
from t2
UNION ALL
select id
from t3) t
group by id
having Number > 10
order by Number desc;
select
id,
count(*) as Number
from
(
select
id
from
t1
UNION ALL
select
id
from
t2
UNION ALL
select
id
from
t3
)t
group by
id
HAVING
Number > 10
order by
Number desc;
Try that - I think its easier to debug if you make your query easy to read...