Avoid joining same table multiple times - sql

I need help in avoiding joining same table multiple times. Here is my sample query.
Table1 have 3 columns ABC_ID,DEF_ID,XYZ_ID and is associated to table2 on ID column . 3 column values in table1 can be null and If values are present then i need to return associated value from table 2 using different column names as in select statement.
As i am using left join i ended up joining table2 three times with table1 on each type if ID column which is having lot of performance issues. How can i write this in different way to avoid join multiple times. Here is sample data. Any help is appreciated
select
(
CASE
WHEN ( table2.ID = table1.ABC_ID)
THEN table2.ID_VAL
ELSE 'TEST1'
END ) AS "TEST1",
(
CASE
WHEN (table2a.ID = table1.DEF_ID)
THEN table2a.ID_VAL
ELSE 'TEST2'
END ) AS "TEST2",
(
CASE
WHEN (table2b.ID = table1.XYZ_ID)
THEN table2b.ID_VAL
ELSE 'TEST3'
END ) AS "TEST3"
from table1 table1
left join table2 table2 on (table2.ID=table1.ABC_ID)
left join table2 table2a on ( table2a.id=table1.DEF_ID)
left join table2 table2b on ( table2b.id=table1.XYZ_ID)
where table1.Id_NUM='1'
Table1
Id_NUM ABC_ID DEF_ID XYZ_ID
1 12345 456789 32145
2 null 456789 32145
3 12345 null null
Table2
ID ID_VAL
12345 abcded
456789 kjwsddk
321456 wedfgfv
OUTPUT
TEST1 TEST2 TEST3
12345 456789 32145

Your joins are fine, but the query can be simplified:
select coalesce(t2a.ID_VAL, 'TEST1') as test1,
coalesce(t2d.ID_VAL, 'TEST2') as test2,
coalesce(t2x.ID_VAL, 'TEST3') as test3
from table1 t1 left join
table2 t2a
on t2a.ID = t1.ABC_ID left join
table2 t2d
on t2d.id = t1.DEF_ID left join
table2 t2x
on t2x.id = t1.XYZ_ID
where t1.Id_NUM = 1;
Notes:
The table aliases should be meaningful. In this case, the aliases include abbreviations for the column used for the join.
Presumably, id_num is a number, so don't use single quotes for the value.
There is no reason to escape the column names. The double quotes just add query clutter.
The case expressions can be replaced by coalesce(), which is simpler (this is not exactly the same if id_val can be NULL, but I'm guessing that doesn't happen).
There is no reason to avoid joining the table three times. That is what your data model requires, because you have three separate foreign key references.

Related

how to make a simple query that matches column values to a look-up then matches further columns if no match is found

This is a simplified version of a problem I have. Say I’ve got three variables all of the same type, in three columns of table1, and an id field. They are all codes. Mostly they map to variables (group identifyers say) contained in a look up in table2. I want to write a query that does the following:
For each of my records I want to return the variable in table2 that my matches the code in the first of the three columns in table1. However, if the variable in this column contains a value that does not have a match in table2, I want to try for a match using column2. If that one does not match, use the one in column3.
I want the query result to contain the ID from table1 and the match from table2. If there is no match at all, then I want the query to contain a row with the id and n/a.
In this example there are just two values that match in my lookup. I'm actually mapping across 12 columns with a few hundreds of unique code values and several million rows of data.
Table1
id col1 col2 col3
1 V21 G22 T21
2 E30 W21 S34
3 Y11 U29 Q66
Table2
cat_code class_group
V21 group1
W21 group2
Query result
id class_group
1 group1
2 group2
3 n/a
So here in the desired result the record id 1 gets to match the very first column, and returns the corresponding variable, the second record can't get a match on the first but finds one on the second column and the third records can't match any value in any of the three columns so it throws an n/a.
I'm fairly new to SQL - I'm not sure whether this can be achieved in a simple query or whether it needs a functon.
select t1.id,
coalesce(t21.class_group, t22.class_group, t23.class_group) class_group
from Table1 t1
left join Table2 t21 on t21.cat_code = t1.col1
left join Table2 t22 on t22.cat_code = t1.col2
left join Table2 t23 on t23.cat_code = t1.col3
Just like Joel wrote... but he's quicker than I am :)
SELECT [Id], COALESCE(C1.[class_group], C2.[class_group], C2.[class_group], 'N/A')
FROM Table1 AS T1
LEFT JOIN Table2 AS C1 ON C1.[cat_code] = T1.[col1]
LEFT JOIN Table2 AS C2 ON C2.[cat_code] = T1.[col2]
LEFT JOIN Table2 AS C3 ON C3.[cat_code] = T1.[col3]
http://sqlfiddle.com/#!6/ffb01/3
Try this sql query:
SELECT table1.id, table2.class_group
FROM table1
INNER JOIN table2 ON table1.col1 = table2.cat_code
UNION
SELECT table1.id, table2.class_group
FROM table1
INNER JOIN table2 ON table1.col2 = table2.cat_code
SELECT table1.id, table2.class_group
FROM table1
INNER JOIN table2 ON table1.col3 = table2.cat_code

Getting the value upon match from the ref table

I have 2 tables
Select distinct
ID
,ValueA
,Place (How to get the Place value from the table 2 based on the Match between 2 columns ValueA and ValueB
Here Table2 is just a ref Table I''m using)
,Getdate() as time
Into #Temp
From Table1
For example when we receive value aa in ValueA column - I want the value of "Place" = "LA"
For example when we receive value bb in ValueA column - I want the value of "Place" = "TN"
Thanks in advance!
SELECT A.ID
, A.ValueA
, B.Place
, GETDATE() INTO #TempTable
FROM Table1 A INNER JOIN Table2 B
ON A.ValueA = B.ValueB
You can do this dude:
Select ID, ValueA, Place, getdate() as Date FROM Table1 INNER JOIN Table2 on Table1.ValueA = table2.ValueB.
Hope this works dude!!!
Regards...
Select
t1.ID
,t1.ValueA
,t2.Place
,Getdate() as time
Into #Temp
From Table1 t1
inner join Table2 t2 on t1.ValueA = t2.ValueB
I believe you are looking to do an inner join:
SELECT Table1.ID, Table1.ValueA, Table2.Place
FROM Table1
INNER JOIN Table2 ON Table1.ValueA = Table2.ValueB
Assumption: ValueB on table 2 is the primary key (or at least UNIQUE and therefore a candidate key).
Also, the DISTINCT is redundant assuming that ID is a primary key. Furthermore, you more than likely do not need a temporary table since a join can be used as an inner SELECT in most databases.
The exact syntax may depend on your particular database engine.

Select data from multiple table

I have the following:
Table1 IdTable1, IdTable2, IdTable3
Table2 IdTable2, Title
Table3 IdTable3, FName, LName
I Need the content of Table1 with the Title, FName, LName
I have tried
SELECT T2.Title, T3.FName, T3.LName
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.IdTable2 = T2.IdTable2
LEFT JOIN Table3 T3 ON T1.IdTable3 = T3.IdTable3
All what I get is the Table2 with the other columns NULL or the 2 columns of Table3 with the first column NULL.
Table 1 Contains
1 2 1
2 2 1
3 2 5
Table 2 Contains
1 Mr
2 Madame
Table3 Contains
1 A B
2 C D
3 E F
4 G H
5 I J
The Results of all my Queries are
Madame Null Null
Madame Null Null
Madame Null Null
or
NULL A B
NULL A B
NULL I J
Your SQL is fine as long as you want to return partial results.
Have you verified the actual data is correct? You are using a LEFT JOIN. This means rows in T1 will be returned even if there is no matching data in T2 or T3. If there are no matching rows in one of those tables, the columns in that table will be NULL.
If you include all of the columns in T1 in your result set, you will see that there is indeed data in T1, but there is no matching data in T2 or T3. In cases where T3 columns are NULL, that means there is data in T1 and T2 but not T3.
It looks to me like you've got a referential integrity problem. You may need to add foreign keys with drop constraints or fix some application logic problems when creating or deleting records.
I guess your Table1 is a pivot table for Table2 and Table3. I will do something like below.
SELECT T2.Title, T3.FName, T3.LName
FROM Table1 T1, Table2 T2, Table3 T3 WHERE T2.IdTable2 = T1.IdTable2 and T3.IdTable3 = T1.IdTable3

sql simple 3 table join using same table?

I have two tables:
Table 1
id, name1
Table 2
id, name2a, name2b
Table 2's column names name2a, and name2b are references to table 1's id. I need to create a query that pulls both the names out of table 1 based on the id's used in Table 2.
Therefore, if Table one contained:
1 Peter
2 Paul
And Table 2 contained:
1 1 2
2 2 2
Then a select statement should give me:
Peter Paul
Paul Paul
I've gone around the bend trying to build this SQL and the best I came up with was:
SELECT table1.name AS 'name', table1.name AS 'Other name'
FROM table1, table2
WHERE table1.id = table2.name2a
Which only gives me the name2a column correctly.
Any help appreciated! I guess I need to do a join, but I'm really struggling...
Start with your 2nd table and join TWICE to table 1 (different aliases respectively), then get the name field from each aliased Table1 entry.
select
T2.ID,
TJ1.Name1 as FirstName,
TJ2.Name1 as SecondName
from
Table2 t2
join Table1 TJ1
on t2.Name2a = TJ1.ID
join Table1 TJ2
on t2.Name2b = TJ2.ID
select foo.*, t1.x, t2.y
join t1 on t1.id = foo.a
join t1 as t2 on t2.id = foo.b
If there's a chance that col a or col b is null, use a left join.
Have you tried using an INNER JOIN?
SELECT table1.name AS 'name', table1.name AS 'Other name'
FROM table1 INNER JOIN table2 ON table1.id = table2.name2a;
Sorry if I'm no help, not that great at SQL myself hehe.
Your problem is that you need to reference table1 twice: once for the plain table1.name and again to look up what table2 is pointing at. You can join one table in multiple times if you give them aliases:
SELECT t1.name1, o.name1
FROM table1 t1
JOIN table2 t2 ON t1.id = t2.name2a
JOIN table1 o ON t2.name2b = o.id -- And JOIN back to table1 to get the name1

Find SQL rows that are not shared between two tables with identical fields

I have two tables with identical fields that share many rows. I'd like to list all the rows in one table that cannot be matched in the other. Specifically, these two tables are two different versions of an experiment where the results differ slightly. An example is something like this:
|TableA|
--------
horse
cat
cow
table
|TableB|
--------
horse
cat
chair
I'd like to be able to see that TableA is missing chair from TableB and possibly in a different query that TableB is missing cow and table are missing from TableA.
My thought was to do some sort of outer join on all fields, then sort out the rows with nulls in them, but this seems heavy handed. Is this the way to go or is there are more elegant/efficient approach?
Using NOT IN:
SELECT a.column
FROM TABLE_A a
WHERE a.column NOT IN (SELECT b.column
FROM TABLE_B b)
Using NOT EXISTS:
This is a good one if you need to compare more than one column...
SELECT a.column
FROM TABLE_A a
WHERE NOT EXISTS(SELECT NULL
FROM TABLE_B b
WHERE b.column = a.column)
Using LEFT JOIN/IS NULL:
SELECT a.column
FROM TABLE_A a
LEFT JOIN TABLE_B b ON b.column = a.column
WHERE b.column IS NULL
Because of the table aliases, you could swap the table names without changing the rest of the query to see the opposite--rows from TABLE_B that aren't in TABLE_A.
be conscious when you are using IN clause for NULLABLE columns
If you want a single listing of all the rows that are in the left table and not the right one and all the rows that are in the right table and not the left table:
CREATE TABLE test1 (
idOne int identity primary key
,nameOne nvarchar (3)
)
CREATE TABLE test2 (
idTwo int identity primary key
,nameTwo nvarchar (3)
)
INSERT INTO test1 (nameOne) VALUES
('one'),
('two'),
('thr')
INSERT INTO test2 (nameTwo) VALUES
('one'),
('tre')
SELECT 'test2 row', idOne, nameOne, idTwo, nameTwo FROM test1 t1
RIGHT JOIN test2 t2 ON
t1.idOne = t2.idTwo and
t1.nameOne = t2.nameTwo
WHERE idONE is NULL
OR idTwo is NULL
UNION ALL
SELECT 'test1 row', idOne, nameOne, idTwo, nameTwo FROM test1 t1
LEFT JOIN test2 t2 ON
t1.idOne = t2.idTwo and
t1.nameOne = t2.nameTwo
WHERE idOne is NULL
OR idTwo is NULL