Counting record without count function - mysql

Human table:
ID Name
1 Peter
2 Peter
3 Peter
4 Tom
5 Tom
6 Mary
7 Paul
If I want to select a name which is containing 3 or more times in the human table, I can write the query like this:
Select name, count(name)
From Human
Group By name
Having count(name) >= 3
But I need to write a query without having and count function now. So, how to implement this query?

No GROUP BY, no HAVING, no COUNT - but a double self join. Doesn't make much sense, but it works!
select distinct t1.name
from tablename t1
join tablename t2 on t1.name = t2.name and t1.id <> t2.id
join tablename t3 on t1.name = t3.name and t1.id <> t3.id and t2.id <> t3.id
BTW, tell you teacher you found this solution on the Internet...
Demo here:
SQLFiddle

WITH cte
AS (
SELECT NAME
,SUM(1) AS NameCount
FROM Human
GROUP BY NAME
)
SELECT *
FROM cte
WHERE NameCount >= 3
or
SELECT *
FROM (
SELECT NAME
,SUM(1) AS NameCount
FROM Human
GROUP BY NAME
) MyTable
WHERE NameCount >= 3

Related

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'

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

Query group by 2 column

I have 1 table with 4 columns
id, name, key, date
1,'A' ,'x1','2015-11-11'
2,'A' ,'x1','2015-11-11'
3,'B' ,'x2','2015-11-11'
4,'B' ,'x2','2015-11-11'
5,'A' ,'x1','2015-11-12'
6,'A' ,'x1','2015-11-12'
7,'B' ,'x2','2015-11-12'
8,'B' ,'x2','2015-11-12'
9,'D' ,'x3','2015-11-12'
I want group by [key] and [date]. Result I want is:
2015-11-11 2
2015-11-12 1
2: date 2015-11-11 have 4 rows (1,2,3,4) but duplicate key, so when group by we only have 2 row.
1: date 2015-11-12 have 5 rows (5,6,7,8,9) but have 4 rows (5,6,7,8) duplicate with date 2015-11-11, I don't want calculator => we only have 1 rows (9)
I'm sorry for my english. I hope you can understand my question.
Please help me every way. I'm using mysql.
select key, date, (select count(*) from tablename t2
where t2.key = t1.key
and t2.date = t1.date
and not exists (select 1 from tablename t3
where t3.key = t2.key
and t3.date < t2.date))
from tablename t1
You can use a correlated sub-query to count that date's keys. Do not count if that date's key-value have already been found for an older date.
Alternative solution:
select t1.key, t1.date, count(*)
from tablename t1
LEFT JOIN (select key, min(date) as date from tablename group by key) t2
ON t2.key = t1.key and t2.date = t1.date
group by t1.key, t1.date

How can I add subtotal to table in MySQL?

Assume my table looks like the following:
id count sub_total
1 10 NULL
2 15 NULL
3 10 NULL
4 25 NULL
How can I update this table to look like the following?
id count sub_total
1 10 10
2 15 25
3 10 35
4 25 60
I can do this easy enough in the application layer. But I'd like to learn how to do it in MySQL. I've been trying lots of variations using SUM(CASE WHEN... and other groupings to no avail.
If your id field is sequential and growing then a correlated subquery is one way:
select *, (select sum(count) from t where t.id <= t1.id)
from t t1
or as a join:
select t1.id, t1.count, sum(t2.count)
from t t1
join t t2 on t2.id <= t1.id
group by t1.id, t1.count
order by t1.id
To update your table (assuming the column sub_total already exists):
update t
join (
select t1.id, sum(t2.count) st
from t t1
join t t2 on t2.id <= t1.id
group by t1.id
) t3 on t.id = t3.id
set t.sub_total = t3.st;
Sample SQL Fiddle showing the update.

how to find maximum if i have more than one answer

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