mysql max function in group by - mysql

I try to get items in mysql, I need to remove from result t2 items, that have status_id = 17 and status_change_date less then max date_created for this t1
t1:
-----
|id |
-----
| 1 |
-----
t2:
---------------------------------------------------------------
| id | t1_id | status_change_date | status_id | date_created |
---------------------------------------------------------------
| 1 | 1 | 2006-02-12 | 17 | 2004-02-12 |
| 2 | 1 | 2006-02-12 | 17 | 2006-02-12 |
| 3 | 1 | 2010-02-12 | 17 | 2007-02-12 |
| 4 | 1 | 2006-02-12 | 17 | 2008-02-12 |
---------------------------------------------------------------
so in result I should to see only item with id 3, cause only in this case status_change_date is after max date_created for items, that have reference to t1 item with id 1
SELECT t1.*, t2.*
FROM t1 JOIN
(
SELECT t2.*,
MAX(date_created) AS max_date FROM t2 WHERE t2.id NOT IN
(
SELECT t2.id FROM t2
WHERE
status_id = 17
and status_change_date < max_date
)
GROUP BY t1_id
) t2 ON t1.id = t2.t1_id
But i got error cause sql don't know what is max_date. How I should to get this value?

From what I understand of joins, your 'from' should come AFTER your 'select' statements.
select *,left(name,1) as L1 from artists order by name limit 5;

You can store value to temporary variable and use to compare:
SELECT t1.*, t2.*
FROM t1 JOIN
(
SELECT t2.*,
#max_date:=MAX(date_created) AS max_date FROM t2 WHERE t2.id NOT IN
(
SELECT t2.id FROM t2
WHERE
status_id = 17
and status_change_date < #max_date
)
GROUP BY t1_id
) t2 ON t1.id = t2.t1_id

You can go with anyone of the following queries:
SELECT t1.*,
t2.*,
Max(date_created) AS max_date
FROM t1
JOIN t2
ON t1.id = t2.t1_id
WHERE status_id = 17
GROUP BY status_change_date
HAVING status_change_date > max_date;
Or
SELECT t1.*,
t2.*
FROM t1
JOIN t2
ON t1.id = t2.t1_id
WHERE status_id = 17
AND status_change_date > (SELECT Max(date_created)
FROM t2);

Related

How get results only if the endDate NOT greater than today

I need only the ids where the endDate is not greater than today
or all endDates of the id are expired
table 1 t1
id |
---
1
2
3
4
table 2 t2
id | t1_id | endDate
-----------------------
1 | 2 | 2019-01-01
2 | 3 | 2019-01-01
3 | 3 | 2020-01-01
4 | 3 | 2025-01-01
Query
SELECT t1.id ,t2.endDate
FROM table_1 t1
LEFT JOIN table_2 t2 ON t2.t1_id = t1.id
WHERE NOT(t2.endDate > CURDATE())
AND ???
I need this result:
t1.id | t2.endDate
-----------------------
2 | 2019-01-01
If I understand your requirement correctly you can use NOT EXISTS:
SELECT t1.id, t2.endDate
FROM table_1 t1
INNER JOIN table_2 t2 ON t2.t1_id = t1.id
WHERE NOT EXISTS
(
SELECT 1
FROM table_2 t
WHERE t.t1_id = t2.t1_id AND t.endDate > CURDATE()
)
Demo here

Join table group by with sort desc

I have 2 table
Table 1
id | value
-----------
1 | a
2 | b
3 | c
4 | d
Table 2
id | table1_id | date
------------------------
1 | 1 | 01-01-2020 1:00:00
2 | 1 | 01-01-2020 2:00:00
3 | 1 | 05-01-2020 1:00:00 (*)
4 | 2 | 05-01-2020 1:00:00
5 | 3 | 06-01-2020 1:00:00
6 | 3 | 06-01-2020 2:00:00 (*)
7 | 2 | 07-01-2020 1:00:00 (*)
I want to join table 1 to table 2. get row of table 2 is max value date and group by table1_id
Like exxample, i want get data like this
id | value | table1_id | date
-------------------------------------------------
1 | a | 1 | 05-01-2020 1:00:00
2 | b | 2 | 07-01-2020 1:00:00
3 | c | 1 | 06-01-2020 2:00:00
4 | d | NULL | NULL
I tryed like this, but not work true
SELECT tb1.*, tb2.* FROM table1 AS tb1
LEFT JOIN
( SELECT * FROM table2 ORDER BY date DESC ) AS tb2
ON tb1.id = tb2.table1_id
GROUP BY table1_id
Can someone help me ? Thanks all <3
The old school way of doing this in MySQL might be to join to a subquery which finds the maximum date in the second table for each table1_id:
SELECT
t1.id,
t1.value,
t2.table1_id,
t2.date
FROM table1 t1
LEFT JOIN
(
SELECT t2.table1_id, t2.date
FROM table2 t2
INNER JOIN
(
SELECT table1_id, MAX(date) AS max_date
FROM table2
GROUP BY table1_id
) t
ON t.table1_id = t2.table1_id AND
t.max_date = t2.date
) t2
ON t2.table1_id = t1.id;
Demo
You can try this:
SELECT id, value, table1_id, max(date) date
FROM
(SELECT t1.id, t1.value, t2.table1_id, t2.date
FROM table1 t1 LEFT JOIN table2 t2
ON t1.id = t2.table1_id
) qry
GROUP BY id, value, table1_id
You can also use window function as below
SELECT tb1.*, tb2.table1_id, tb2.date
FROM table1 AS tb1
LEFT JOIN
( SELECT table2.*,
row_number() over(partition by table1_id ORDER BY date DESC) as seq_num
FROM table2 ) AS tb2
ON tb1.id = tb2.table1_id
Where tb2.seq_num = 1 ;
Here is a demo - https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=f52a5a930411dcc04900a1a5bacfe6e9. The demo contains both NULL and not NULL versions.
I strongly recommend that you use window functions for this -- assuming you want mulple columns. This looks like:
select t1.*, t2.*
from table1 t1 left join
(select t2.*,
row_number() over (partition by table1_id order by date DESC) as seqnum
from table2 t2
) t2
on t1.id = t2.table1_id and seq_num = 1 ;
However, if you just want one column -- and the table1_id is redundant so I see no need to include it -- then a correlated subquery is often the fastest method:
select t1.*,
(select max(t2.date) from table2 t2 where t1.id = t2.table1_id)
from table1 t1;
In particular, this can take advantage of an index on table2(table1_id, date).

How can I get a record which has two corresponding columns which are multiple in SQL?

For example, I have two tables:
ID | Name
------------
1 | test 1
2 | test 2
ID2| ID | Age
--------------
1 | 1 | 18
2 | 1 | 18
3 | 1 | 19
4 | 2 | 18
5 | 2 | 19
I want to have all records that have columns which are multiple in name with age but I don't know how to do that.
I want an output like this:
Name | Age
--------------------
test 1 | 18
test 1 | 18
Can anyone help me?
Try following query:
Select t1.*, t2.*
from table1 t1
join table2 t2
on t1.id = t2.id
join (select id, age
from table2
group by id, age
having count(*) > 1
) t3
on t1.id = t2.id and t2.id = t3.id and t2.age = t3.age
Use exists:
select t.*
from t
where exists (select 1
from t t2
where t2.name = t.name and t2.age = t.age and
t2.id <> t.id
);
With an index on (name, age, id), this should be the fastest approach.
You can also use an IN on tupples.
And a GROUP BY can be combined with a HAVING to only get those that have duplicate (name, age).
SELECT t1.Name, t2.Age
FROM YourTable2 t2
LEFT JOIN YourTable1 t1 ON t1.ID = t2.ID
WHERE (t2.ID, t2.Age) IN (
SELECT ID, Age
FROM YourTable2
GROUP BY ID, Age
HAVING COUNT(*) > 1
);

SQL select MAX from other table

I have two tables.
table1:
| ID | NAME |
|----|------|
| 1 | aaa |
| 2 | aaa |
| 3 | aaa |
| 4 | bbb |
| 5 | bbb |
table2:
| ID | DATE |
|----|----------|
| 1 | 12/07/10 |
| 2 | 12/07/13 |
| 3 | 12/07/16 |
| 4 | 12/07/08 |
| 5 | 12/07/20 |
Help me pls, I don't know how to SELECT MAX ID in table1 by date in table2.
For example result should be:
for "aaa": ID 3 from table2
for "bbb": ID 5 from table2
I'm trying something like that:
DATE = (SELECT MAX(DATE) FROM table2 t2, table1 t1 WHERE t1.NAME = "aaa")
But it's not working... Have you got some idea?
You need to add an additional condition (t1.id = t2.id) for the join:
SELECT MAX(DATE)
FROM table2 t2, table1 t1
WHERE t1.NAME = "aaa"
AND t1.id = t2.id
But please - don't join with comma - use explicit JOIN syntax instead:
SELECT MAX(DATE)
FROM table2 t2
JOIN table1 t1
ON t1.id = t2.id
WHERE t1.NAME = "aaa"
You can also get all max dates for all names at once using GROUP BY name:
SELECT t1.NAME, MAX(t2.DATE)
FROM table2 t2
JOIN table1 t1
ON t1.id = t2.id
GROUP BY t1.NAME
I have tried to take the MAX Date using this query.
Note: In the table the date format should be (Y-m-d) and the field should be set to date in order to manipulate the operations
Table - 1(Name: test1)
Table - 2(Name: test2)
QUERY TO GET MAX FROM OTHER TABLE
SELECT MAX(dates) FROM test2 JOIN test1 WHERE test1.name='aaa'
OUTPUT
Hope so this query will solve your problem.
select ID from Table1 where date= (select max(date) from T2 where name= 'aaa'
i didn't fully got you. But I think this is how you want it.... If you had these two table as one table then it would work as charm.
Or THIS ,with Two Table like you asked for
SELECT T1.Id FROM T1 INNER JOIN T2
ON T1.Id = T2.Id
where T2.date = (select max(T2.date) from T1 where T1.name= 'aaa')

Find values C that exists in every B from A

I have a table with 3 fields ID,A,B.
I want to find every B that occurs in every A from some ID
For example:
ID | A | B |
----------------------
1 | 10 | 22 |
1 | 10 | 24 |
1 | 11 | 22 |
| | |
2 | 12 | 31 |
2 | 13 | 33 |
| | |
3 | 14 | 34 |
Should return:
ID | B |
-------------
1 | 22 |
3 | 34 |
because for every different value of A from ID 1 , B = 22 occurs.
Same for id 3.
Any idea how I can do it?
Thank you in advance.
Sql Fiddle Demo
You can use this query to validate what rows your need.
SELECT T1.B, T1.ID, COUNT(DISTINCT A), T2.total_id_a
FROM Table1 T1
JOIN (SELECT ID , COUNT(DISTINCT A) as total_id_a
FROM Table1
GROUP BY ID) T2
ON T1.ID = T2.ID
GROUP BY B, ID;
But this will provide the result you want.
SELECT ID, B
FROM (
SELECT T1.ID, T1.B, COUNT(DISTINCT A), T2.total_id_a
FROM Table1 T1
JOIN (SELECT ID , COUNT(DISTINCT A) as total_id_a
FROM Table1
GROUP BY ID) T2
ON T1.ID = T2.ID
GROUP BY B, ID
HAVING COUNT(DISTINCT A) = T2.total_id_a
) T
OUTPUT
| ID | B |
|----|----|
| 1 | 22 |
| 3 | 34 |
# For case ID=1 and B=22 for example above
SELECT DISTINCT t1.ID, t1.B
FROM yourtable AS t1
INNER JOIN yourtable AS t2
ON t2.B = t1.B
AND t2.A <> t1.A
AND t1.ID = t2.ID
UNION
# For case ID=3 and B=34 for example above
SELECT DISTINCT t1.ID, t1.B
FROM yourtable AS t1
INNER JOIN yourtable AS t2
ON t2.B = t1.B
AND t2.A = t1.A
AND t1.ID = t2.ID
LEFT JOIN yourtable AS t3
ON t3.ID = t1.ID
AND (t3.A <> t1.A OR t3.B <> t1.B)
WHERE t3.ID IS NULL