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

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

Related

How to determine if there is a missing value in joined table

I am trying to find the "users" that are missing a value in a 2nd table with the value of column "A" = 16 and then column "B" = 0.
I am looking for these values because that would give me the ability to run a query adding a row for each user that is missing the row with the values of A = 16 and B = 0.
So here is the relevant structure of the tables that we would be joining on.
There are two tables, table 1 and table 2
Table 1
ID
parent id
table 2
table1_id
A
B
The problem I am running into is that table2 can have records associated with the table1_id but still needing to verify if the table2 if there is not a row with table1_id, A missing value 16 while B is missing value 0.
Here is the current idea I am working off of for the sql query
SELECT
*
FROM
table1
LEFT JOIN
table2 ON table1.id = table2.table1_id
WHERE
table1.id IS NOT NULL
AND table2.id IS NULL;
This will give me all the table1_ids that are missing records from table2 but does however would not pull the rows where there are rows for the table1_id but however does not determine if there are missing rows with the column A with value 16 or Column B = 0.
If you are able to answer that would be greatly appreciated. I just currently cannot think of a way I can logically create a query that would do this.
So, you want all rows from table 1
And you want rows from table 2 that are A=16, B=0
And you want to know where the relationship breaks down between table1 and table2:
SELECT t1.*
FROM
table1 t1
LEFT JOIN
(
SELECT * FROM table2 WHERE A=16 and B=0
) a16b0
ON
t1.id = a16b0.table1_id
WHERE
a16b0.table1_id IS NULL
There are more ways to skin this cat, but this should be fairly understandable in the sense of "join table1 to (just the a16/b0 rows from table2)"
Another form you might get on with uses EXISTS:
SELECT * FROM table1 t1
WHERE NOT EXISTS(
SELECT null FROM table2 t2
WHERE t2.table1_id = t1.id AND t2.A = 16 AND t2.B = 0
)
In english it's "Select all from table 1 where, for any particular t1 row, there does not exist a t2 row that has: a matching id in table1_id, a 16 in a, a 0 in b"
A slightly less popular form (historical performance reasons probably) would be perhaps:
SELECT * FROM table1 t1
WHERE id NOT IN (
SELECT table1_id FROM table2 WHERE A = 16 AND B = 0
)
"select everything from table1 where the row's id is not in the list of IDs that are a16/b0 from table 2" - in essence this forms a "big list of everything we dont want" and then says "get me everything that isn't in the list of don't-wants"
This is the solution.
SELECT
*
FROM
table1
LEFT JOIN
table1.id = table2.table1_id AND table2.A = 16 AND table2.B = 0
WHERE
table2.id IS NULL;
#jon Armstrong, thanks for the help.

SQL If two column values dont match, then show all values that dont match

I have two tables joined up together
I need to see if Product Code from table 1 (On the left) matches with the on on the right, based on their barcodes.. I have managed to inner join the barcodes and show only barcodes that match up. Just the prdouct code is the problem now...
Is this what you want?
select t1.*
from table1 t1
where not exists (select 1
from table2 t2
where t2.code = t1.product_code and t2.barcode = t1.barcode
);
This selects rows from table1 with no matches in table2.

Get rows matching the combination of ids in sql server 2008

I have a combination of ids present in a table1 as listed below :
Combi1 Combi2
---------------
1000 26341
26341 26580
1000 26580
Now, I have a table2 which has rows as listed below :
ID CombiIDs
------------------
26131 26341
26131 26580
26131 21234
21411 26580
21411 21212
21411 21234
I want to get those rows from table2 where there is match of combination of table1. i.e
1000,26341(this combination from table1) doesn't have any row in match as a combination in table 2 whereas 26341,26580 (this combination from table1) has rows matching in table2(i.e.26131).
I want an sql query to achieve this kind of output.
select *
from T2 T21
inner join T2 T22
on T21.ID = T22.ID
inner join T1 T1
on T21.CombiIDs = T1.Combi1
and T22.CombiIDs = T1.Combi2

Are "from Table1 left join Table2" and "from Table2 right join Table1" interchangeable?

For example, there are two tables:
create table Table1 (id int, Name varchar (10))
create table Table2 (id int, Name varchar (10))
Table1 data as follows:
Id Name
-------------
1 A
2 B
Table2 data as follows:
Id Name
-------------
1 A
2 B
3 C
If I execute both below mentioned SQL statements, both outputs will be the same:
select *
from Table1
left join Table2 on Table1.id = Table2.id
select *
from Table2
right join Table1 on Table1.id = Table2.id
Please explain the difference between left and right join in the above SQL statements.
Select * from Table1 left join Table2 ...
and
Select * from Table2 right join Table1 ...
are indeed completely interchangeable. Try however Table2 left join Table1 (or its identical pair, Table1 right join Table2) to see a difference. This query should give you more rows, since Table2 contains a row with an id which is not present in Table1.
Table from which you are taking data is 'LEFT'.
Table you are joining is 'RIGHT'.
LEFT JOIN: Take all items from left table AND (only) matching items from right table.
RIGHT JOIN: Take all items from right table AND (only) matching items from left table.
So:
Select * from Table1 left join Table2 on Table1.id = Table2.id
gives:
Id Name
-------------
1 A
2 B
but:
Select * from Table1 right join Table2 on Table1.id = Table2.id
gives:
Id Name
-------------
1 A
2 B
3 C
you were right joining table with less rows on table with more rows
AND
again, left joining table with less rows on table with more rows
Try:
If Table1.Rows.Count > Table2.Rows.Count Then
' Left Join
Else
' Right Join
End If
You seem to be asking, "If I can rewrite a RIGHT OUTER JOIN using LEFT OUTER JOIN syntax then why have a RIGHT OUTER JOIN syntax at all?" I think the answer to this question is, because the designers of the language didn't want to place such a restriction on users (and I think they would have been criticized if they did), which would force users to change the order of tables in the FROM clause in some circumstances when merely changing the join type.
select fields
from tableA --left
left join tableB --right
on tableA.key = tableB.key
The table in the from in this example tableA, is on the left side of relation.
tableA <- tableB
[left]------[right]
So if you want to take all rows from the left table (tableA), even if there are no matches in the right table (tableB), you'll use the "left join".
And if you want to take all rows from the right table (tableB), even if there are no matches in the left table (tableA), you will use the right join.
Thus, the following query is equivalent to that used above.
select fields
from tableB
right join tableA on tableB.key = tableA.key
Your two statements are equivalent.
Most people only use LEFT JOIN since it seems more intuitive, and it's universal syntax - I don't think all RDBMS support RIGHT JOIN.
I feel we may require AND condition in where clause of last figure of Outer Excluding JOIN so that we get the desired result of A Union B Minus A Interaction B.
I feel query needs to be updated to
SELECT <select_list>
FROM Table_A A
FULL OUTER JOIN Table_B B
ON A.Key = B.Key
WHERE A.Key IS NULL AND B.Key IS NULL
If we use OR , then we will get all the results of A Union B
select *
from Table1
left join Table2 on Table1.id = Table2.id
In the first query Left join compares left-sided table table1 to right-sided table table2.
In Which all the properties of table1 will be shown, whereas in table2 only those properties will be shown in which condition get true.
select *
from Table2
right join Table1 on Table1.id = Table2.id
In the first query Right join compares right-sided table table1 to left-sided table table2.
In Which all the properties of table1 will be shown, whereas in table2 only those properties will be shown in which condition get true.
Both queries will give the same result because the order of table declaration in query are different like you are declaring table1 and table2 in left and right respectively in first left join query, and also declaring table1 and table2 in right and left respectively in second right join query.
This is the reason why you are getting the same result in both queries. So if you want different result then execute this two queries respectively,
select *
from Table1
left join Table2 on Table1.id = Table2.id
select *
from Table1
right join Table2 on Table1.id = Table2.id
Select * from Table1 t1 Left Join Table2 t2 on t1.id=t2.id
By definition: Left Join selects all columns mentioned with the "select" keyword from Table 1 and the columns from Table 2 which matches the criteria after the "on" keyword.
Similarly,By definition: Right Join selects all columns mentioned with the "select" keyword from Table 2 and the columns from Table 1 which matches the criteria after the "on" keyword.
Referring to your question, id's in both the tables are compared with all the columns needed to be thrown in the output. So, ids 1 and 2 are common in the both the tables and as a result in the result you will have four columns with id and name columns from first and second tables in order.
*select *
from Table1
left join Table2 on Table1.id = Table2.id
The above expression,it takes all the records (rows) from table 1 and columns, with matching id's from table 1 and table 2, from table 2.
select *
from Table2
right join Table1 on Table1.id = Table2.id**
Similarly from the above expression,it takes all the records (rows) from table 1 and columns, with matching id's from table 1 and table 2, from table 2. (remember, this is a right join so all the columns from table2 and not from table1 will be considered).

How do I Write a SQL Query With a Condition Involving a Second Table?

Table1
...
LogEntryID *PrimaryKey*
Value
ThresholdID - - - Link to the appropriate threshold being applied to this log entry.
...
Table2
...
ThresholdID *PrimaryKey*
Threshold
...
All fields are integers.
The "..." thingies are there to show that these tables hold a lot more imformation than just this. They are set up this way for a reason, and I can't change it at this point.
I need write a SQL statement to select every record from Table1 where the Value field in that particular log record is less than the Threshold field in the linked record of Table2.
I'm newish to SQL, so I know this is a basic question.
If anyone can show me how this SQL statement would be structured, it would be greatly appreciated.
SELECT T1.*
FROM Table1 T1
JOIN Table2 T2 ON T2.ThresholdID = T1.ThresholdID
WHERE T2.Threshold > T1.Value
SELECT t1.*
FROM dbo.Table1 t1 INNER JOIN dbo.Table2 t2 ON t1.ThresholdID = t2.ThresholdID
WHERE t2.Threshold > t1.Value
SELECT * from table1 t1 join table2 t2 on (t1.thresholdId = t2.thresholdId)
where t1.value < t2.threshold;
SELECT t1.LogEntryID, t1.Value, t1.ThresholdID
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.ThresholdID = t2.ThresholdID
WHERE t1.Value < t2.threshold
SELECT * FROM Table1
JOIN Table2
ON table1.ThresholdID = table2.ThresholdID --(assuming table 2 holds the same value to link them together)
WHERE
value < thresholdvalue
A 'JOIN' connects 2 tables based on the 'ON' clause (which can be multipart, using 'AND' and 'OR')
If you have 3 entries in table 2 which share table1's primary key (a one-to-many association) you will receive 3 rows in your result set.
for the tables below, for example:
Table 1:
Key Value
1 Hi
2 Bye
Table 2:
Table1Key 2nd_word
1 You
1 fellow
1 friend
2 now
this query:
SELECT * FROM Table1
JOIN Table2
on table1.key = table2.table1key
gets this result set:
Key Value Table1Key 2nd_word
1 Hi 1 You
1 Hi 1 fellow
1 Hi 1 friend
2 Bye 2 now
Note that JOIN will only return results when there is a match in the 2nd table, it will not return a result if there is no match. You can LEFT JOIN for that (all fields from the second table will be NULL).
JOINs can also be strung together, the result from the previous JOIN is used in place of the original table.