This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
Closed 11 months ago.
new to SQL but I'll try to be clear,
I have 3 table, which have corresponding key columns. I need to select the row the MAX Value of a set column, for EACH of it's corresponding column.
Table1
ID1 Value1
1 Marie
2 Max
3 John
Table2
ID2 Value2
1 First
2 Second
3 Third
Table3
ID1 ID2
1 1
1 2
2 1
2 2
2 3
3 1
So far I have something like so;
SELECT T1.Value1, T2.Value2 FROM Table1 T1
INNER JOIN Table3 T3 ON T1.ID1 = T3.ID1
INNER JOIN Table2 T2 ON T3.ID2 = T2.ID1
WHERE (That's where I can't formulate correctly)
So far my tables are correctly joined, but I want to output only the rows where ID2 is at it's max value for the corresponding ID1.
So we'd have
ID1 ID2
1 2
2 3
3 3
And so, from correspondence of value we'd finally have.
Value1 Value2
Marie Second
Max Third
John First
Any help? Also, group by is prohibited.
You must use MAX in WHERE condition:
SELECT
T1.Value1,
T2.Value2
FROM
Table1 T1
INNER JOIN Table3 T3 ON T1.ID1 = T3.ID1
INNER JOIN Table2 T2 ON T3.ID2 = T2.ID1
WHERE
T3.ID2 = (
SELECT
MAX(T3_alias.ID2)
FROM
Table3 AS T3_alias
WHERE
T3_alias.ID1 = T1.ID1
)
Related
I have 2 tables in MySQL database that I would like to join, where I would like to contain all results from table1.
My tables looks like this:
table1
id
name
1
name1
2
name2
3
name3
4
name4
5
name5
6
name6
7
name7
8
name8
table2
id
table1_id
myfield
1
3
test1
2
2
test2
3
1
test1
4
4
test2
5
5
null
6
2
null
What I am trying to achieve is to get a table which contains all the rows from table1 and only the data that is joined from table2.
This is my query:
select * from table1 as t1
left join table2 as t2 on t1.id = t2.table1_id
where myfield="test1"
group by t1.id
But this is not what I want to achieve.
What I want to achieve is to get all records from table1 and to have all related records from table2 where table2.myfield="test1". And for the other for table2.mytable to have null (if they do not fulfil table2.myfield="test1").
Any help is much appreciated!
Thanks!
move the where clause to the on clause:
select * from table1 as t1
left join table2 as t2 on t1.id = t2.table1_id
and myfield="test1"
group by t1.id
BTW: some DBMS does not allow select * with group by. So select the id and some aggregated values or remove group by id
I have 3 tables:-
table1 :-
ReportType | ResourceId
t2 123
t3 5
table2:-
Id | Name | Created
1 A 10
2 B 11
123 C 12
table3:-
Id | Name | Created
4 D 13
5 E 14
6 F 15
table1's ResourceId and table2 and 3's Id column have same values
I want to create a 4th table like this:-
ReportType | ResourceId | Name | Created
t2 123 C 12
t3 5 E 14
such that wherever table1's ReportType is t2 I want the Name and Created value from table2 for the condition table1.ResourceId = table2.Id and wherever table1's ResourceType is t3 I want the Name and Created value from table3 for the condition table1.ResourceId = table3.Id.
PS: This isn't some sort of HomeWork. I have been stuck at this query for the past 1 hour, I have read various answers and tried a few queries of my own before posting the question. Any help would really be appreciated.
Explanation in comments :)
--here we join first and second table, but we filter results to include only ReportType = t2
select t1.ReportType, t1.ResourceId, t2.Name, t2.Created from table1 as t1 join table2 as t2 on t1.ResourceId = t2.id
where t1.ReportType = 't2'
union all
--here we join first and third table, but we filter results to include only ReportType = t3
select t1.ReportType, t1.ResourceId, t3.Name, t3.Created from table1 as t1 join table3 as t3 on t1.ResourceId = t3.id
where t1.ReportType = 't3'
You can use the below query:
select report_type, resourceid,name, created from dbo.t2, dbo.t1
where report_type='t2' and ResourceId=id
UNION
select report_type, resourceid,name, created from dbo.t3, dbo.t1
where report_type='t3' and ResourceId=id;
I have 3 tables as follows
Table1
Id Name
1 abcd
2 bcd
3 dabc
Table2
Id2 Name2
2 xyz
3 def
4 mno
Table3
Id Id2 Value
1 4 1
2 3 1
3 4 1
Now,
From table1 : I have to select all Id where Name is %abc%
From table2: I have to select Id2 where Name2 is "mno"
From Table3: I have to change value to 0 from 1 where Id's value are from Table1 and Id2 is from Table2.
Table 1:
select Id from Table1 where Name like '%abc%'
Table2 :
select Id2 from Table2 where Name2 = "mno"
Table 3:
update Table3 set Value = 0 where Id in() and Id2=
But, I dont know how to make it 1 single query. Can anyone please guide me up ?
Refer to: prior stack article
You've not explained how T1 relates to T2, So I have assumed a cross join.
Whenever you have a record in T1 with name like '%abc%' (1,3) in your data..
and whenever you have a record in T2 with a name equal to 'mno' 4 then you want the value in table 3 to be 0
so the select we generate should produce
1,4
3,4
and when we inner join this back to table 3 it only selects
Id Id2 Value
1 4 1
3 4 1
Now we generate an update based on this select as outlined in the link provided above...
UPDATE table3
INNER JOIN (
SSELECT t1.ID t1ID, t2.id t2ID
FROM table1 t1
CROSS JOIN table2
WHERE t1.name like '%abc%'
and t2.name like = 'mno') B
on B.t1ID = t3.Id
and B.t2ID = T3.ID2
SET value = 0
Giving us a result of
Id Id2 Value
1 4 0
2 3 1
3 4 0
if we select * from table3
update t3
set t3.Value = 0
from Table3 t3
inner join Table1 t1
on t3.Id = t1.Id
inner join Table2 t2
on t3.Id2 = t2.Id2
where t1.Name like '%abc%' and t2.Name2 = 'mno'
OR
update Table3
set value = 0
where Id in (select Id from Table1 where Name like '%abc%')
and Id2 in (select Id2 from Table2 where Name2 = 'mno')
You should think about UPDATE ... WHERE EXISTS as follows:
update Table3 set Value = 0
WHERE EXISTS (SELECT 1 FROM Table1 where Name LIKE '%abc%' AND Table1.Id=Table3.Id )
AND EXISTS (SELECT 1 FROM Table2 where Name2 = "mno" AND Table2.Id2=Table3.Id2)
In SQL, suppose that I have table A
ID
--
1
3
5
and table B
ID2
---
1
2
3
4
5
6
To get the result similar to:
ID | ID2
----------
1 | 1
1 | 2
3 | 3
3 | 4
5 | 5
5 | 6
For an explanation, an element in column ID2 will be mapped to the highest value in the column ID that is less than or equal to the said element in ID2.
For example, 4 in column ID2 is mapped to 3 from column ID, because 3 is the largest value in column ID which is less than or equal to 4.
Is it possible at all to do this in sql?
What I would do is start by joining the two tables on the condition that the id in the first table is less than or equal to that in the second table, like this:
SELECT t1.id, t2.id AS id2
FROM t1
JOIN t2 ON t2.id >= t1.id;
Once you have that, you can select the maximum id from the first table, and group by the id from the second table to get the largest pairs:
SELECT MAX(t1.id) AS id, t2.id AS id2
FROM t1
JOIN t2 ON t2.id >= t1.id
GROUP BY t2.id;
SQL Fiddle seems to be down but I will update with a link as soon as I can.
SELECT MAX(A.ID) ID, B.ID2
FROM A
INNER JOIN B ON B.ID2 >= A.ID
GROUP BY B.ID2
If you only need the matching ID column:
select b.*,
(select max(ID) from a where a.ID <= b.ID2) as a_Id
from b
If you need more columns:
select *
from a
join
(
select b.*,
(select max(ID) from a where a.ID <= b.ID2) as a_Id
from b
) as b
on a.Id = b.a_Id
Given the following table structures:
T1:
id a
1 1
2 2
3 3
T2:
id t1_id b
1 1 1
2 1 2
3 2 3
I need to add the value of t2.b to the value of t1.a where t2.t1_id = t1.id.
A simple update with a join like the following isn't working:
UPDATE t1
JOIN t2
ON t2.t1_id = t1.id
SET t1.a = t1.a + t2.b
WHERE t2.id IN(1,2)
Expected T1 result (adds 1 and 2 to t1.a = 1; 3 to t1.a = 2):
id a
1 4
2 5
3 3
Actual T1 result (only adds 1 to t1.a = 1; 3 to t1.a = 2):
id a
1 2
2 5
3 3
At the moment I'm looking at a select that computes the full sum of values to be added using a group by, and then that result set is joined to the update... This seems like overkill for something so simple though! Does anyone have an elegant and efficient solution?
Came up with this real quickly.
UPDATE T1 AS t
JOIN (
SELECT
t1_id, SUM(b) AS sum_total
FROM
T2
WHERE
t1_id IN (1, 2)
GROUP BY
T2.t1_id
) AS t2 ON t.id = t2.t1_id
SET t.a = t.a + t2.sum_total;