Join Two Column into New Column - sql

How do I combine both COLUMN2 of table1 and table2?
SELECT COLUMN1, COLUMN2 FROM TABLE1
C1 C2
A 1
SELECT COLUMN1, COLUMN2 FROM TABLE2
C1 C2
A 1
B 2
C 2
C1 C2 C3
A 1 1
B 2 0
C 2 0
I want to have a third column combining column2 of both tables base on column1 which has a value of A, B, C. Then if it's null in either table the value should be 0 Please see third sample for sample result.

So you want to match records from both tables on the basis of key column COLUMN1. If a record exists in only one table display that. COLUMN3 indicates whether the key exists in both tables.
This solution uses FULL OUTER JOIN, so it will work whether a record exists in T1 but not T2 or in T2 but not T1. The coalesce() function displays the first non-null argument.
SELECT coalesce(t1.COLUMN1, t2.COLUMN1) as COLUMN1
, coalesce(t1.COLUMN2, t2.COLUMN2) as COLUMN2
, case when t1.COLUMN1 is not null
and t2.COLUMN1 is not null then 1 else 0 end as COLUMN3
FROM TABLE1 t1
full outer join TABLE2 t2
on t1.COLUMN1 = t2.COLUMN1
Assumption. This query ignores the scenario where t1.COLUMN1 = t2.COLUMN1 but t1.COLUMN2 != t2.COLUMN2. It will just show t1.COLUMN2 in the result set. If this is not the outcome you desire please **edit your question ** to include more sample data and the full required output.

To avoid confusion, lets say table_1 has 2 columns(C1,C2) and table_2 has 2 columns(C3,C4). I just renamed column 1 & 2 of table_2 to column 3 & 4.
From What I understood from your question you want all records of table_2 in the result along with a new column which contains values from table_1 based c3 column.
The requires Table_1 right outer join Table_2 with NVL to display 0 against which value is missing in table_1 (B & C)
Full Query is as follows
SELECT Y.COLUMN_3, Y.COLUMN_4, NVL (X.COLUMN_2, 0)
FROM TABLE_1 X RIGHT OUTER JOIN TABLE_2 Y ON (X.COLUMN_1 = Y.COLUMN_3);
Hope this answers your query. Please mark the answer accepted if this solves your problem.

Please try this code...
select dbo.Table_2.C1,
dbo.Table_2.C2,
[C3] = (select Case when dbo.Table_1.C2 = dbo.Table_2.C2 then 1 else 0 end)
from dbo.Table_2
left join dbo.Table_1 on dbo.Table_1.C1 = dbo.Table_2.C1

This is what you must be looking for
SELECT tbl1.C1,
tbl2.C2,
[C3] =
(
SELECT CASE
WHEN tbl1.C2 Is Null OR tbl2.C2 is null
THEN 0
ELSE 1
END
)
FROM tbl1
INNER JOIN tbl2 ON tbl1.C1 = tbl2.C1;

Try This
select table2.c1,
table2.c2,
case when table1.c2 is null or
table2.c2 is null
then 0 else 1 end c3
from table1,table2 where table1.c1(+)=table2.c1;

Related

SQL Server - Set a variable if a value from one table exists in another

I have tables that are set up as shown below:
Table 1:
ID Name Date
1 a 2000-01-01
2 b 2001-01-01
3 c 2002-01-01`
Table 2:
ID Name
2 b
3 c
I would like to return all in Table 1 and then have a column that will hold a variable of either 'Yes' or 'No', based on whether they exist in Table 2, as shown below.
As shown:
Results:
Name Date Yes/No
a 2000-01-01 No
b 2001-01-01 Yes
c 2002-01-01 Yes
I have:
DECLARE #boolean as varchar(10)
IF EXISTS(
SELECT ID FROM Table 2
)
SET #boolean = 'Yes'
ELSE SET #boolean = 'No'
SELECT Name, Date, #boolean as 'Yes/No'
FROM Table 1
LEFT JOIN Table 2 u ON Table 1.ID = Table 2.ID
However, this returns the results as shown below:
Name Date Yes/No
a 2000-01-01 Yes
b 2001-01-01 Yes
c 2002-01-01 Yes
Any ideas on how to manipulate this query to return what is expected?
One option would be to LEFT JOIN the first table to the second one, and then check each record in the first table to see whether its ID matched anything in the second table.
SELECT t1.Name,
t1.Date,
CASE WHEN t2.ID IS NOT NULL THEN 'Yes' ELSE 'No' END AS [Yes/No]
FROM table1 t1
LEFT JOIN table2 t2
ON t1.ID = t2.ID
Demo here:
Rextester
By using LEFT JOIN and checking using CASE if there is no matching result on the second table (t2.ID IS NULL), you can easily get what you need as below:
SELECT Name, Date, CASE WHEN t2.ID IS NULL THEN 'No' ELSE 'Yes' END AS [Yes/No]
FROM Table1 t1 LEFT JOIN Table2 t2 ON t1.ID = t2.ID
If a left join might return multiple unwanted results you can use outer apply() instead:
select t1.*, [Yes/No]=coalesce(x.Yes,'No')
from table_1 t1
outer apply (
select Yes='Yes'
from table_2 t2
where t1.id = t2.id
) x
Select * , case when exists(select 1 from Table2 as b where b.ID = a.ID and b.Name = a.Name) then 'Yes' else 'No' end as 'Yes/No'
From table1 as a
Your query:
DECLARE #boolean as varchar(10)
IF EXISTS(
SELECT ID FROM Table 2
)
SET #boolean = 'Yes'
will always return true because you only check whether ID exists (which always exists records in table2), you forgot to check that should be the ID exists in table1, and you probably do not do in that way, because the indicator is a dynamic value.

Querying two tables to filter data using select case

I have two tables
Table 1 looks like this
ID Repeats
-----------
A 1
A 1
A 0
B 2
B 2
C 2
D 1
Table 2 looks like this
ID values
-----------
A 100
B 200
C 100
D 300
Using a view I need a result like this
ID values Repeats
-------------------
A 100 NA
B 200 2
C 100 2
D 300 1
that means, I want unique ID, its values and Repeats. Repeats value should display NA when there are multiple values against single ID and it should display the Repeats value in case there is single value for repeats.
Initially I needed to display the max value of repeats so I tried the following view
ALTER VIEW [dbo].[BookingView1]
AS
SELECT bv.*, bd2.Repeats FROM Table1 bv
JOIN
(
SELECT distinct bd.id, bd.Repeats FROM table2 bd
JOIN
(
SELECT Id, MAX(Repeats) AS MaxRepeatCount
FROM table2
GROUP BY Id
) bd1
ON bd.Id = bd1.Id
AND bd.Repeats = bd1.MaxRepeatCount
) bd2
ON bv.Id = bd2.Id;
and this returns the correct result but when trying to implement the CASE it fails to return unique ID results. Please help!!
One method uses outer apply:
select t2.*, t1.repeats
from table2 t2 outer apply
(select (case when max(repeats) = min(repeats) then max(repeats)
else 'NA'
end) as repeats
from table1 t1
where t1.id = t2.id
) t1;
Two notes:
This assumes that repeats is a string. If it is a number, you need to cast it to a string.
repeats is not null.
For the sake of completeness, I'm including another approach that will work if repeats is NULL. However, Gordon's answer has a much simpler query plan and should be preferred.
Option 1 (Works with NULLs):
SELECT
t1.ID, t2.[Values],
CASE
WHEN COUNT(*) > 1 THEN 'NA'
ELSE CAST(MAX(Repeats) AS VARCHAR(2))
END Repeats
FROM (
SELECT DISTINCT t1.ID, t1.Repeats
FROM #table1 t1
) t1
LEFT OUTER JOIN #table2 t2
ON t1.ID = t2.ID
GROUP BY t1.ID, t2.[Values]
Option 2 (does not contain explicit subqueries, but does not work with NULLs):
SELECT DISTINCT
t1.ID,
t2.[Values],
CASE
WHEN COUNT(t1.Repeats) OVER (PARTITION BY COUNT(DISTINCT t1.Repeats), t1.ID) > 1 THEN 'NA'
ELSE CAST(t1.Repeats AS VARCHAR(2))
END Repeats
FROM #table1 t1
LEFT OUTER JOIN #table2 t2
ON t1.ID = t2.ID
GROUP BY t1.ID, t2.[Values], t1.Repeats
NOTE:
This may not give desired results if table2 has different values for the same ID.

SQL version of VLOOKUP

I am new to SQL and if you have a spare moment, I was wondering whether anybody could help me replicate the Excel Vlookup function in SQL please?
From some research, I am suspecting that it is one of the join functions that I require, however, I don't want to just select data that is contained in both tables - I just want to lookup the value in 1 table against another.
If the data is contained in the lookup table then return the value and if not, just return NULL.
I have given a couple of example tables below to help illustrate my question.
Please note that Products 'C' and 'D' are not in Table2 but they are still in the result table but with NULL value.
Also I have a large number of unique products, so I am not looking for an answer which includes hard-coding, for example; CASE WHEN [Product] = 'A' THEN...
TABLE1
Product Quantity
-------------------
A 10
B 41
D 2
C 5
B 16
A 19
C 17
A 21
TABLE 2
Product Cost
-----------------
A £31.45
B £97.23
RESULT TABLE
Product Quantity Cost
-----------------------------
A 10 £31.45
B 41 £97.23
D 2 NULL
C 5 NULL
B 16 £97.23
A 19 £31.45
C 17 NULL
A 21 £31.45
It looks as if you need an outer join, I'll use a left one in my example:
select t1.Product, t1.Quantity, t2.Cost
from table1 as t1
left outer join table2 as t2
on t1.Product = t2.Product
You can also leave out the outer keyword:
select t1.Product, t1.Quantity, t2.Cost
from table1 as t1
left join table2 as t2
on t1.Product = t2.Product
Here's an updated version of Lennart's answer which really works great.
select *
from table1 as t1
left outer join table2 as t2
on t1.Product = t2.Product
and t2.Product <> ''
left outer join table3 as t3
on t1.Product = t3.Product2
and t3.Product2 <> ''
The point is, you need to exclude rows where the join table column is blank, otherwise you will return way too many rows then table1 has. A true vlookup does not add any rows to the left table.
I even added a third table for effect.

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

grouping records in one temp table

I have a table where one column has duplicate records but other columns are distinct. so something like this
Code SubCode version status
1234 D1 1 A
1234 D1 0 P
1234 DA 1 A
1234 DB 1 P
5678 BB 1 A
5678 BB 0 P
5678 BP 1 A
5678 BJ 1 A
0987 HH 1 A
So in the above table. subcode and Version are unique values whereas Code is repeated. I want to transfer records from the above table into a temporary table. Only records I would like to transfer are where ALL the subcodes for a code have status of 'A' and I want them in the temp table only once.
So from example above. the temporary table should only have
5678 and 0987 since all the subcodes relative to 5678 have status of 'A' and all subcodes for 0987 (it only has one) have status of A. 1234 is ommited because its subcode 'DB' has status of 'P'
I'd appreciate any help!
Here's my solution
SELECT Code
FROM
(
SELECT
Code,
COUNT(SubCode) as SubCodeCount
SUM(CASE WHEN ACount > 0 THEN 1 ELSE 0 END)
as SubCodeCountWithA
FROM
(
SELECT
Code,
SubCode,
SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END)
as ACount
FROM CodeTable
GROUP BY Code, SubCode
) sub
GROUP BY Code
) sub2
WHERE SubCodeCountWithA = SubCodeCount
Let's break it down from the inside out.
SELECT
Code,
SubCode,
SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END)
as ACount
FROM CodeTable
GROUP BY Code, SubCode
Group up the codes and subcodes (Each row is a distinct pairing of Code and Subcode). See how many A's occured in each pairing.
SELECT
Code,
COUNT(SubCode) as SubCodeCount
SUM(CASE WHEN ACount > 0 THEN 1 ELSE 0 END)
as SubCodeCountWithA
FROM
--previous
GROUP BY Code
Regroup those pairings by Code (now each row is a Code) and count how many subcodes there are, and how many subcodes had an A.
SELECT Code
FROM
--previous
WHERE SubCodeCountWithA = SubCodeCount
Emit those codes with have the same number of subcodes as subcodes with A's.
It's a little unclear as to whether or not the version column comes into play. For example, do you only want to consider rows with the largest version or if ANY subcde has an "A" should it count. Take 5678, BB for example, where version 1 has an "A" and version 0 has a "B". Is 5678 included because at least one of subcode BB has an "A" or is it because version 1 has an "A".
The following code assumes that you want all codes where every subcode has at least one "A" regardless of the version.
SELECT
T1.code,
T1.subcode,
T1.version,
T1.status
FROM
MyTable T1
WHERE
(
SELECT COUNT(DISTINCT subcode)
FROM MyTable T2
WHERE T2.code = T1.code
) =
(
SELECT COUNT(DISTINCT subcode)
FROM MyTable T3
WHERE T3.code = T1.code AND T3.status = 'A'
)
Performance may be abysmal if your table is large. I'll try to come up with a query that is likely to have better performance since this was off the top of my head.
Also, if you explain the full extent of your problem maybe we can find a way to get rid of that temp table... ;)
Here are two more possible methods. Still a lot of subqueries, but they look like they will perform better than the method above. They are both very similar, although the second one here had a better query plan in my DB. Of course, with limited data and no indexing that's not a great test. You should try all of the methods out and see which is best for your database.
SELECT
T1.code,
T1.subcode,
T1.version,
T1.status
FROM
MyTable T1
WHERE
EXISTS
(
SELECT *
FROM MyTable T2
WHERE T2.code = T1.code
AND T2.status = 'A'
) AND
NOT EXISTS
(
SELECT *
FROM MyTable T3
LEFT OUTER JOIN MyTable T4 ON
T4.code = T3.code AND
T4.subcode = T3.subcode AND
T4.status = 'A'
WHERE T3.code = T1.code
AND T3.status <> 'A'
AND T4.code IS NULL
)
SELECT
T1.code,
T1.subcode,
T1.version,
T1.status
FROM
MyTable T1
WHERE
EXISTS
(
SELECT *
FROM MyTable T2
WHERE T2.code = T1.code
AND T2.status = 'A'
) AND
NOT EXISTS
(
SELECT *
FROM MyTable T3
WHERE T3.code = T1.code
AND T3.status <> 'A'
AND NOT EXISTS
(
SELECT *
FROM MyTable T4
WHERE T4.code = T3.code
AND T4.subcode = T3.subcode
AND T4.status = 'A'
)
)
In your select, add a where clause that reads:
Select [stuff]
From Table T
Where Exists
(Select * From Table
Where Code = T.Code
And Status = 'A')
And Not Exists
(Select * From Table I
Where Code = T.Code
And Not Exists
(Select * From Table
Where Code = I.Code
And SubCode = I.SubCode
And Status = 'A'))
In English,
Show me the rows,
where there is at least one row with status 'A',
and there are NO rows with any specific subcode,
that do not have at least one row with that code/subcode, with status 'A'
INSERT theTempTable (Code)
SELECT t.Code
FROM theTable t
LEFT OUTER JOIN theTable subT ON (t.Code = subT.Code AND subT.status <> 'A')
WHERE subT.Code IS NULL
GROUP BY t.Code
This should do the trick. The logic is a little tricky, but I'll do my best to explain how it is derived.
The outer join combined with the IS NULL check allows you to search for the absence of a criteria. Combine that with the inverse of what you're normally looking for (in this case status = 'A') and the query succeeds when there are no rows that do not match. This is the same as ((there are no rows) OR (all rows match)). Since we know that there are rows due to the other query on the table, all rows must match.