Select rows from a table based on max value in different table - mysql

I'm looking for a MySQL query to extract values like in the following example:
TABLE1:
ID name
25 ab
24 abc
23 abcd
22 abcde
21 abcdef
TABLE2:
ID ID_TABLE1 total
1 25 0
2 25 1
3 25 2
4 25 3
5 23 1
6 22 0
7 22 1
8 21 0
9 21 2
10 24 10
11 24 7
I want to return all TABLE1 rows where max value of total column (in TABLE2) is < 3.
So the results should be:
ID name
23 abcd
22 abcde
21 abcdef
I tried this:
SELECT t1.*
FROM TABLE1 t1
INNER JOIN (
SELECT MAX( total ) AS max_total, ID_TABLE1
FROM TABLE2
GROUP BY total, ID_TABLE1
) t2
ON t1.ID = t2.ID_TABLE1
WHERE t2.max_total < 3
but it's not the result I want.

Try this:
SELECT t1.ID, t1.name
FROM TABLE1 t1
INNER JOIN (SELECT ID_TABLE1, MAX(total) AS max_total
FROM TABLE2
GROUP BY ID_TABLE1
) t2 ON t1.ID = t2.ID_TABLE1
WHERE t2.max_total < 3;

Your inner query groups the results by id_table and by total. Since the maximum of total per total is the value itself, it makes the inner query somewhat meaningless. Just remove the total from the group by clause and you should be OK:
SELECT t1.*
FROM TABLE1 t1
INNER JOIN (
SELECT MAX( total ) AS max_total, ID_TABLE1
FROM TABLE2
GROUP BY ID_TABLE1
) t2
ON t1.ID = t2.ID_TABLE1
WHERE t2.max_total < 3

SELECT t1.*
FROM TABLE1 t1
INNER JOIN (
SELECT MAX( total ) AS max_total, ID_TABLE1
FROM TABLE2
GROUP BY ID_TABLE1
having t2.max_total < 3
) t2
ON t1.ID = t2.ID_TABLE1

Here is a way to do using left join without using any subquery and group by clauses.
select t1.* from table1 t1
join table2 t2
on t1.id = t2.id_table1
left join table2 t3 on
t2.id_table1 = t3.id_table1
and t2.total < t3.total
where t3.id is null
and t2.total < 3
Another way is
select t1.* from table1 t1
join table2 t2 on t1.id = t2.id_table1
where not exists(
select 1 from table2 t3
where t2.id_table1 = t3.id_table1
and t2.total < t3.total
)
and t2.total < 3;

SELECT t1.*
FROM TABLE1 t1
INNER JOIN (
SELECT MAX( total ) AS max_total, ID_TABLE1
FROM TABLE2
where total > 3 GROUP BY total, ID_TABLE1
) t2
ON t1.ID != t2.ID_TABLE1

There's a simpler way without using GROUP or MAX:
SELECT * FROM table1
WHERE id NOT IN (
SELECT id_table1 FROM table2 WHERE total >= 3
);
The subquery selects all rows in table2 that have a total >= 3. Then we select those rows from table1 that are not in the subquery result.

Related

Find rows with consecutive dates

Is it possible to know which customer came at the bar 3 consecutive days? (john in my case)
Thanks in advance
Name
Age
Date
Amount
Paul
12
2021-12-01
20
John
19
2021-12-01
10
Jack
17
2021-13-01
7
John
19
2021-13-01
8
John
19
2021-14-01
17
so I would approach this by
SELECT FROM Table
LEFT JOIN Table As PrevDay on PrevDay.Customer = Table.Customer
AND PrevDay.date = DATEADD(DAY,-1,Table.Date)
LEFT JOIN Table AS NextDay on NextDay,Customer = Table.Customer
AND NextDay.Date = DATEADD(DATE,1,Table.Date)
WHERE PrevDay.Customer is not NULL
AND NextDay.Customer is not null
Assuming that the data type of the column Date is DATE you can use a self join and aggregation:
SELECT DISTINCT t1.Name
FROM tablename t1 INNER JOIN tablename t2
ON t2.Name = t1.Name AND ABS(DATEDIFF(t1.Date, t2.Date)) = 1
GROUP BY t1.Name, t1.Date
HAVING COUNT(DISTINCT t2.Date) = 2;
Or, a more scalable solution:
SELECT DISTINCT t1.Name
FROM tablename t1 INNER JOIN tablename t2
ON t2.Name = t1.Name AND t2.Date BETWEEN t1.Date AND t1.Date + INTERVAL 2 DAY
GROUP BY t1.Name, t1.Date
HAVING COUNT(DISTINCT t2.Date) = 3;
You can remove DISTINCT from COUNT(DISTINCT t2.Date) if the combination of Name and Date is unique in the table.
See the demo.

Query doesn't show table1 row which id is not in table2 using inner join

I have two table,
table1
=======================================
pid pname coldate col4
---------------------------------------
1 Tesitng Name1 2019-01-01 self
2 Tesitng Name2 2020-01-01 self
3 Tesitng Name3 2020-03-01 self2
4 Tesitng Name4 2020-04-04 self2
5 Tesitng Name5 2020-04-05 self3
in table1 pid have unique key
table2 //which have more than 600k rows
=======================================
billid rate pid
---------------------------------------
1 30 1
2 50 1
3 40 1
4 10 3
///In table2 billid have unique key
I try to show all rows of table1 with sum of rate column of table2 where table1.pid=table2.pid
Result shoul be like this
table1
=======================================================
pid pname coldate col4 total
-------------------------------------------------------
1 Tesitng Name1 2019-01-01 self 120
2 Tesitng Name2 2020-01-01 self 0
I am using this query
SELECT
t1.*
, ttl.total
FROM table1 t1
inner join
(SELECT pid, sum(rate) as total
FROM table2
GROUP BY pid) as ttl
on ttl.pid=t1.pid
WHERE
t1.coldate BETWEEN '2020-01-01' AND '2020-04-01'
AND t1.col4 = 'self'
ORDER BY t1.pid DESC;
but it doesn't show table1 row which pid is not in table2
please tell me the fastest way to perform this action
I am using php with mysql..
You have in your subquery already a bug , you have to remove the second pid like in the xample below.
To get all rows from table1 you need a LEFT JOIN instead of a INNER JOIN
But your Where clause reduces everything to 1 row anyway.
SELECT
t1.*
, ttl.total
FROM table1 t1
LEFT join
(SELECT pid, sum(rate) as total
FROM table2
GROUP BY pid) as ttl
on ttl.pid=t1.pid
WHERE
t1.coldate BETWEEN '2020-01-01' AND '2020-04-01'
AND t1.col4 = 'self'
ORDER BY t1.pid DESC;
Your title says it all, as if you know you need a LEFT JOIN:
SELECT t1.*, ttl.total
FROM table1 t1 LEFT JOIN
(SELECT pid, sum(rate) as total
FROM table2
GROUP BY pid
) ttl
ON ttl.pid = t1.pid
WHERE t1.coldate BETWEEN '2020-01-01' AND '2020-04-01' AND
t1.col4 = 'self'
ORDER BY t1.pid DESC;
For performance, you should probably use a correlated subquery:
SELECT t1.*,
(SELECT SUM(tt1.rate)
FROM table2 tt1
WHERE ttl.pid = t1.pid
) total
FROM table1 t1
WHERE t1.coldate BETWEEN '2020-01-01' AND '2020-04-01' AND
t1.col4 = 'self'
ORDER BY t1.pid DESC;
Then you want indexes on table1(col4, coldate, pid) and table2(pid, rate).

how to exclude first and last row if group it on particular id

I have sample table with data like this
id uniqueid values
1 6 0
2 6 1
3 6 2
4 6 0
5 6 1
I want result like this
id uniqueid values
2 6 1
3 6 2
4 6 0
I tried like this
select id,uniqueid,values
FROM t1
WHERE
id not in(SELECT concat(MAX(message_id_pk),',',min(message_id_pk)) FROM t1
where uniqueid=6)
and `uniqueid`=6
GROUP BY uniqueid
but its not working
You can achieve the desired results by doing self join, Inner query will get the the max and min ids for per group and outer query will filter out the results by using minid and maxid
select a.*
from demo a
join (
select `uniqueid`,min(id) minid, max(id) maxid
from demo
where uniqueid=6
group by `uniqueid`
) b using(`uniqueid`)
where a.id > b.minid and a.id < b.maxid /* a.id <> b.minid and a.id <> b.maxid */
Demo
Also you can do it by using 2 sub-queries with EXISTS to exclude the min and max id of each uniqueid.
Query
select `id`, `uniqueid`, `values`
from `your_table_name` t1
where exists (
select 1 from `your_table_name` t2
where t2.`uniqueid` = t1.`uniqueid`
and t2.`id` > t1.`id`
)
and exists(
select 1 from `your_table_name` t2
where t2.`uniqueid` = t1.`uniqueid`
and t2.`id` < t1.`id`
);
Here is a sql fiddle demo
Try this -
SELECT id, uniqueid, values
FROM YOUR_TABLE
WHERE id NOT IN (MIN(id), MAX(id));

SQL mapping from 1 table

I have 2 mysql tables that look like this:
Tabel 1 :
ID NAME
1 car1
2 car2
3 car3
4 car4
Tabel 2 :
car_id liter
2 100
2 300
3 400
1 500
3 600
I want to output something like:
Tabel 3:
car_id liters
car2 100
car2 300
car3 400
car1 500
car3 600
I try to write something like:
SELECT tabel2.car_id
, tabel1.ID
FROM tabel2
, tabel2
INNER
JOIN tabel3
ON tabel2.car_id = tabel1.ID;
I know this is kinda a newbie question, but I'm new to SQL.
Simply join the two tables:
select t1.name, t2.liter
from table1 t1
join table2 t2 on t1.id = t2.car_id
order by t2.liter
select t1.name, t2.liter from table1 t1 ,table2 t2 where t1.id = t2.car_id
order by t2.liter;
You can try this to get the desired result:
select t1.NAME, t2.liter
from table1 t1
INNER JOIN table t2 on t1.id=t2.car_id
ORDER BY t2.liter DESC
Try this:
select t1.name, t2.liter
from table1 t1 ,
table2 t2
here t1.id = t2.car_id ;

Get missing id from table

I have tbl_profilecategory table structure like this:
Id col1
1 50
3 30
4 40
5 50
8 80
9 90
Now I want the missing IDs from table, so the result here should be like this:
Id= 2,6,7
You can use
SELECT t1.id - 1 AS missing_id
FROM mytable t1
LEFT JOIN mytable t2 ON t2.id = t1.id - 1
WHERE t2.id IS NULL
This answer is based here
SELECT a.id+1 AS start, MIN(b.id) - 1 AS end
FROM testtable AS a, testtable AS b
WHERE a.id < b.id
GROUP BY a.id
HAVING start < MIN(b.id)