Join on same column multiple times - sql

how do I join on the same column multiple times, one of the tables is a configuration table with values and other is the data table.
T1:
ID Seq Code1 Code2 Code3
1 001 101 203 305
1 002 107
2 001 103
3 005 213
4 009 320
5 001 101 314
T2 (Config table):
Value Description
101 Strawberry
103 Raspberry
107 Blueberry
111 Banana
203 Cashews
213 Almonds
305 Bellpepper
320 Tomatoes
314 Potatoes
I need to display the code and its relevant description for each ID.
Expected Output:
ID Code1 Description Code2 Description Code3 Description
1 101 Strawberry 203 Cashews 305 Bellpepper
1 107 Blueberry
2 103 Raspberry
3 213 Almonds
4 320 Tomatoes
5 101 Strawberry 314 Potatoes
This is what I have tried so far, however, it is not giving me the desired output:
select distinct ID,code1, T2.description,
code2, T2.description, code3, T2.description
from T1,T2
where (T1.Code1=T2.Value OR T1.Code2=T2.Value or T1.Code3=T2.Value)
How can I achieve this? Sorry if my question is confusing, I can provide more details if needed.

That's multiple outer join with the t2 table:
select a.id, a.seq,
a.code1, d1.description,
a.code2, d2.description,
a.code3, d3.description
from t1 a left join t2 d1 on a.code1 = d1.value
left join t2 d2 on a.code2 = d2.value
left join t2 d3 on a.code3 = d3.value
order by a.id, a.seq;
ID SEQ CODE1 DESCRIPTIO CODE2 DESCRIPTIO CODE3 DESCRIPTIO
----- --- ---------- ---------- ---------- ---------- ---------- ----------
1 001 101 Strawberry 203 Cashews 305 Bellpepper
1 002 107 Blueberry
2 001 103 Raspberry
3 005 213 Almonds
4 009 320 Tomatoes
5 001 101 Strawberry 314 Potatoes

Related

Update query for two tables in oracle based on multiple conditions

Consider i have two table train_reserve and reserve:
train_reserve:
ChangeId
C_Id
Process
Download
trainId
Status
SDate
EDate
Book_date
L_date
BookId
1
1001
1
A
1995
B
05-APR-22
06-APR-22
10-MAR-22
11-MAR-22
111
2
1001
2
B
1995
M
05-APR-22
08-APR-22
10-MAR-22
11-MAR-22
111
3
1002
1
B
1995
B
12-APR-22
14-APR-22
10-MAR-22
11-MAR-22
222
4
1002
2
C
1995
M
12-APR-22
13-APR-22
10-MAR-22
11-MAR-22
222
5
1003
1
A
1995
B
25-MAY-22
25-MAY-22
10-MAR-22
11-MAR-22
333
6
1004
1
A
1995
B
19-MAR-22
20-MAR-22
10-MAR-22
11-MAR-22
444
7
1004
1
B
1995
B
19-MAR-22
20-MAR-22
10-MAR-22
11-MAR-22
555
reserve:
C_Id
trainId
SDate
EDate
L_date
BookId
1001
1995
05-APR-22
08-APR-22
11-MAR-22
111
1002
1995
12-APR-22
13-APR-22
11-MAR-22
222
1003
1995
25-MAY-22
25-MAY-22
11-MAR-22
333
1004
1995
19-MAR-22
20-MAR-22
11-MAR-22
444
1005
1995
19-MAR-22
20-MAR-22
11-MAR-22
555
Below is the input from user:
C_id=1, Process=(1,2), Download=(A,B,C), trainId=1995, Status=(B),Sdate=null,Edate=null,Book_date>='10-MAR-22',L_date=null.
User want to update BookId=null in both tables when C_id>=1001 and Status is B only . i.e I want below output:
train_reserve:
ChangeId
C_Id
Process
Download
trainId
Status
SDate
EDate
Book_date
L_date
BookId
1
1001
1
A
1995
B
05-APR-22
06-APR-22
10-MAR-22
11-MAR-22
111
2
1001
2
B
1995
M
05-APR-22
08-APR-22
10-MAR-22
11-MAR-22
111
3
1002
1
B
1995
B
12-APR-22
14-APR-22
10-MAR-22
11-MAR-22
222
4
1002
2
C
1995
M
12-APR-22
13-APR-22
10-MAR-22
11-MAR-22
222
5
1003
1
A
1995
B
25-MAY-22
25-MAY-22
10-MAR-22
11-MAR-22
null
6
1004
1
A
1995
B
19-MAR-22
20-MAR-22
10-MAR-22
11-MAR-22
null
7
1004
1
B
1995
B
19-MAR-22
20-MAR-22
10-MAR-22
11-MAR-22
null
reserve:
C_Id
trainId
SDate
EDate
L_date
BookId
1001
1995
05-APR-22
08-APR-22
11-MAR-22
111
1002
1995
12-APR-22
13-APR-22
11-MAR-22
222
1003
1995
25-MAY-22
25-MAY-22
11-MAR-22
null
1004
1995
19-MAR-22
20-MAR-22
11-MAR-22
null
1005
1995
19-MAR-22
20-MAR-22
11-MAR-22
null
I am currently using two update statements as below
update train_reserve a
set a.BookId=null
where a.C_Id>=1001
and a.trainId=1995
and a.Process in (1,2)
and a.Download in ('A','B','C')
and a.Status='B'
and a.Book_date>='10-MAR-22'
and not exists (select 1
from train_reserve b
where a.C_Id = b.C_Id
and b.Status='M');
update reserve
set BookId = null
where a.C_Id in (select a.C_Id
from train_reserve a
where a.C_Id >= 1001
and a.trainId=1995
and a.Process in (1,2)
and a.Download in ('A','B','C')
and a.Status='B'
and a.Book_date>='10-MAR-22'
and not exists (select 1
from train_reserve b
where a.C_Id = b.C_Id
and b.Status='M'));
But second query above takes long time to update since i am fetching data from 1st table then updating reserve table.
Is there optimized way to achieve above result?

How to change the Row Number behavior in my T-SQL Query?

I am using SQL Server 2014 and I have the following T-SQL query running against a table (tbl1).
Extract of tbl1:
emp_code Name Address Company
---------------------------------------
100 Peter London ABC
125 Allan Cambridge DCE
125 Allan Cambridge DCE
115 John Suffolk ABC
115 John Suffolk XYZ
154 Mary Highlands ABC
154 Mary Bristol ABC
124 Mary Chester ABC
My T-SQL query stands as follows:
SELECT
[ID],
[Name],
[Address],
[Company],
ROW_NUMBER() OVER (PARTITION BY [emp_code] ORDER BY [Address]) AS RowNumber
FROM
[tbl1]
Output from above query:
emp_code Name Address Company RowNumber
--------------------------------------------------------
100 Peter London ABC 1
125 Allan Cambridge DCE 1
125 Allan Cambridge DCE 2
115 John Suffolk ABC 1
115 John Suffolk XYZ 2
154 Mary Highlands ABC 1
154 Mary Bristol ABC 2
154 Mary Chester ABC 3
Output I'm after:
emp_code Name Address Company RowNumber
---------------------------------------------------------
100 Peter London ABC 1
125 Allan Cambridge DCE 1
125 Allan Cambridge DCE 1
115 John Suffolk ABC 1
115 John Suffolk XYZ 1
154 Mary Highlands ABC 1
154 Mary Bristol ABC 2
154 Mary Chester ABC 3
I want my RowNumber (or change the column name if need be) to change based on the [Address] column for each [emp_code]. If the employee has the SAME address, it should have the same value (that is, 1). Else, it should give the values as in the case of employee "Mary" (above output).
I am assuming the Row_Number() function is not the right one to be used for what I'm after.
Any help would be appreciated.
I think you want DENSE_RANK here rather than ROW_NUMBER():
SELECT [ID], [Name], [Address], [Company],
DENSE_RANK() OVER (PARTITION BY [emp_code]
ORDER BY [Address]) AS DenseRank
FROM [tbl1];
Demo

Getting an element and the next from a table

I have a table with ids, cities and some sequence number, say:
ID CITY SEQ_NO
1 Milan 123
2 Paris 124
1 Rome 125
1 Naples 126
1 Strasbourg 130
3 London 129
3 Manchester 132
2 Strasbourg 128
3 Rome 131
2 Rome 127
4 Moscow 135
5 New York 136
4 Helsinki 137
I want to get the city that comes after Rome for the same id, in this case, I can order them by doing something like:
SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY SEQ_NO) as rownum,
id,
city,
seq_no
FROM mytable
I get:
rownum ID CITY SEQ_NO
1 1 Milan 123
2 1 Rome 125
3 1 Naples 126
4 1 Strasbourg 130
1 2 Paris 124
2 2 Rome 127
3 2 Strasbourg 128
1 3 London 129
2 3 Rome 131
3 3 Manchester 132
1 4 Moscow 135
2 4 Helsinki 137
1 5 New York 136
and, I want to get
ID CITY SEQ_NO
1 Rome 125
1 Naples 126
2 Rome 127
2 Strasbourg 128
3 Rome 131
3 Manchester 132
How do I proceed?
Hmmm . . . I might suggest window functions:
select t.*
from (select t.*,
lag(city) over (partition by id order by seq_no) as prev_city
from mytable t
) t
where 'Rome' in (city, prev_city)

How to use the value in one table to count results in another table?

I want to add a new column on my SQL query that will count the number of times a value on the row appears in a different table.
For example, let's say I have these two separate tables.
Table Name: Table_A
Id | Coach | Team_Color | Team_Number
------------------------------------------
001 | Jane | Orange | 121
002 | Frank | Purple | 232
003 | Tim | Red | 343
Table Name: Table_B
Id | Team_Number | Player_Name
----------------------------------
901 | 121 | Jimmy
902 | 121 | Wesley
903 | 121 | Samantha
904 | 121 | Wendy
905 | 232 | Tim
906 | 232 | Sean
907 | 343 | Andrew
908 | 343 | Erik
909 | 343 | Sarah
910 | 343 | Allison
911 | 343 | Desmond
912 | 343 | Kathryn
I want to end up with something like this:
Id | Coach | Team_Color | Team_Number | Player Count
--------------------------------------------------------
001 | Jane | Orange | 121 | 4
002 | Frank | Purple | 232 | 2
003 | Tim | Red | 343 | 6
The new column called "Player Count" is referencing the Team_Number value in Table_A, and counting the number of instances found on Table_B. How would I compose this into one query?
Solution to your Problem:
SELECT A.Id, A.Coach, A.Team_Color,A.Team_Number,Count(B.Id) AS Player_Count
FROM Table_A AS A
INNER JOIN Table_B B
ON A.Team_Number = B.Team_Number
GROUP BY A.Id, A.Coach, A.Team_Color,A.Team_Number;
OUTPUT:
Id Coach Team_Color Team_Number Player_Count
1 Jane Orange 121 4
2 Frank Purple 232 2
3 Tim Red 343 6
Follow the link to the demo:
http://sqlfiddle.com/#!9/9c6da4/1
EXPLAINATION:
In your problem, you have to use JOIN to join the two tables on a common Column i.e.Team_Number. Now after Joining you will get a result like this:
Id Coach Team_Color Team_Number Id Team_Number Player_Name
1 Jane Orange 121 901 121 Jimmy
1 Jane Orange 121 902 121 Wesley
1 Jane Orange 121 903 121 Samantha
1 Jane Orange 121 904 121 Wendy
2 Frank Purple 232 905 232 Tim
2 Frank Purple 232 906 232 Sean
3 Tim Red 343 907 343 Andrew
3 Tim Red 343 908 343 Erik
3 Tim Red 343 909 343 Sarah
3 Tim Red 343 910 343 Allison
3 Tim Red 343 911 343 Desmond
3 Tim Red 343 912 343 Kathryn
Now Use aggregate function COUNT on above Result to get the final result.

Distinct values one column with other columns from two tables

I'm trying to eliminate duplicate rows from an Access dataset made up of two tables table1 and table2. I want to retrieve the distinct values from one column and fields from two tables, but also retrieve the values of other columns of duplicates and unique values.
Sample data (not actual data):
Table 1:
ID BOM_PART_NAME PART FIND NO POS LCN POS_CT
1 E 0001 1 P0 1
2 A 0002 1 P1 1
3 C 0003 1 P2 1
4 D 0004 1 P3 1
5 F 0005 1 P4 1
Table 2:
ID PART-ATA-NO PART-SN PART-NAME
1 001 A
2 002 B
3 003 C
4 004 1100 D
5 005 1101 E
Table 2:
ID PART-ATA-NO PART-SN PART-NAME
1 001 A
2 002 B
3 003 C
4 004 1100 D
5 005 1101 E
What I'm getting (just showing major columns in result set to keep brief):
ID ... PART FIND NO POS PART-ATA-NO PART-SN
1 001 1 001 1369
2 002 1 002 1444
3 003 1 003 1100
3 003 1 003 1101
3 003 1 003 1102
4 003 2 003 1101
4 003 2 003 1102
5 004 1 004 1101
5 004 1 004 1102
Desired Result:
ID PART FIND NO POS PART-ATA-NO PART-SN
1 001 1 001 1369
2 002 1 002 1444
3 003 1 003 1100
4 003 2 003 1101
5 003 3 003 1102
6 003 4 003 1103
7 003 5 003 1104
8 004 1 004 1105
9 004 2 004 1106
ID PART FIND NO POS PART-ATA-NO PART-SN
1 001 1 001 1369
2 002 1 002 1444
3 003 1 003 1100
3 003 1 003 1101
3 003 1 003 1102
4 003 2 003 1101
4 003 2 003 1102
5 004 1 004 1101
5 004 1 004 1102
Desired Result:
ID PART FIND NO POS PART-ATA-NO PART-SN
1 001 1 001 1369
2 002 1 002 1444
3 003 1 003 1100
4 003 2 003 1101
5 003 3 003 1102
6 003 4 003 1103
7 003 5 003 1104
8 004 1 004 1105
9 004 2 004 1106
With matching PART FIND NO's (and PART-ATA-NO's), POS should be incremented by 1. The SN's should all be unique.
The query I used to join the two tables:
SELECT Table1.*, Table2.[PART-ATA-NO], Table2.[PART-SN]
FROM Table1 INNER JOIN Table2 ON Table1.[PART FIND NO] = Table2.[PART-ATA-NO];
The field I want unique values from is [PART-SN] from table2. I want to select all other fields from table1 and [PART-SN] from table 2, of which all rows should be returned for all distinct rows of [PART-SN]. [PART FIND NO] and [PART-ATA-NO] have equivalent values. Is there a way to join the two tables to get this result?