Combine two tables into one table with separated values - sql-server

This is a simple rather simple question, but for whatever reason I just can't get to a solution.
How do I join the two tables like such that I have get NULL values like this?
Table #T1
A
--
1
2
Table #T2
B
--
3
Desired result:
A B
----
1 NULL
2 NULL
NULL 3
EDIT:
My solution was this
SELECT #T1.A, #T2.B
FROM #t2
RIGHT JOIN #T1 ON 1 = 0
UNION
SELECT #T1.A, #T2.B
FROM #t2
LEFT JOIN #t1 ON 1 = 0
But it seems overly complicated. Anything better?

Use FULL JOIN
select *
from #t1 t1
full outer join #t2 t2 on t1.a = t2.b
or use UNION ALL
select a,Null as b
from #t1
union all
select NULL, b
from #t2
since there is no common records in both the tables, both the query results will look same. When there is a common record, the result will differ. Use the one that suits your requirement

This is the better/simple one
SELECT #T1.A, #T2.B
FROM #t2
FULL OUTER JOIN #T1 ON 1 = 0

Related

How to join the table

Here i have 2 tables and i need to join the table as i am a beginner please help me to solve
Table1 Table2
ins1 ins2 ins3 Insc0
1 2 0 1
3 4 0 2
5 6 0 3
4
5
is this below code right?
select t2.insco from table1 t1
join table2 t2 on t1.ins1=t2.insco
union
select t2.insco from table1 t1
join table2 t2 on t1.ins2=t2.insco
union
select t2.insco from table1 t1
join table2 t2 on t1.ins3=t2.insco
As I mentioned, you need to normalise your data. This is every much overly simplified, due to the simplicity of your data, however, should get you on the right path:
CREATE TABLE dbo.YourTable1 (RowID int--,
--Other columns, but no ins1, 2, etc columns
);
INSERT INTO dbo.YourTable1 (RowID--,
--Other columns
)
VALUES(1),(2),(3);--Obviouslu, again you would have other columns, but not an ins columns
CREATE TABLE dbo.YourTable2 (Insc0 int);
INSERT INTO dbo.YourTable2 (Insc0)
VALUES(1),(2),(3),(4),(5);
CREATE TABLE dbo.LinkTable (RowID int,
Ins int);
INSERT INTO dbo.LinkTable (RowID,
Ins)
VALUES(1,1),(1,2),
(2,3),(2,4),
(3,5),(3,6);
GO
SELECT *
FROM dbo.YourTable1 YT1
JOIN dbo.LinkTable LT ON YT1.RowID = LT.RowID
JOIN dbo.YourTable2 YT2 ON LT.Ins = YT2.Insc0;
GO
--Clean up
DROP TABLE dbo.LinkTable;
DROP TABLE dbo.YourTable2;
DROP TABLE dbo.YourTable1;

Joining tables without a common column in sql server

TABLE1
ID
----
1
2
3
4
5
TABLE2
Name
----
Z
Y
X
W
V
Expected Output:
ID Name
-------------------------
1 NULL
2 NULL
3 NULL
4 NULL
5 NULL
NULL Z
NULL Y
NULL X
NULL W
NULL V
I need a solution for the above scenario by using JOINS in SQL Server.
Using FULL OUTER JOIN, you can get the expected result.
Since there are no common fields, no records from Table1 should match with Table2 and vice versa. So perhaps ON 0 = 1 as the join condition also will work as expected. Thanks Bart Hofland
So the query below also will work:
SELECT T1.Id, T2.[Name]
FROM Table1 T1
FULL OUTER JOIN Table2 T2 ON 0 = 1;
or
SELECT T1.Id, T2.[Name]
FROM Table1 T1
FULL OUTER JOIN Table2 T2 ON T2.[Name] = CAST(T1.Id AS VARCHAR(2));
Demo with the sample data:
DECLARE #Table1 TABLE (Id INT);
INSERT INTO #Table1 (Id) VALUES
(1),
(2),
(3),
(4),
(5);
DECLARE #Table2 TABLE ([Name] VARCHAR(1));
INSERT INTO #Table2 ([Name]) VALUES
('Z'),
('Y'),
('X'),
('W'),
('V');
SELECT T1.Id, T2.[Name]
FROM #Table1 T1
FULL OUTER JOIN #Table2 T2 ON 0 = 1;
Output:
Id Name
-----------------
1 NULL
2 NULL
3 NULL
4 NULL
5 NULL
NULL Z
NULL Y
NULL X
NULL W
NULL V
I don't understand why you'd want this, but to get your expected results you could do this. This is not a join, though.
SELECT ID, NULL as NAME from Table1
UNION ALL
SELECT NULL, NAME from Table2
Edited to add
Since the question specifically requests a solution with a join, Arulkumar's answer of FULL OUTER JOIN is a better fit, and you don't have to worry about what the column data types are.

Why does UNION returns only one null?

I understand null represents missing/unknown value, so a null is not equal to another null because two unknown things cannot be compared. For example
if null = null
select 'nulls are equal'
else
select 'nulls are not equal'
results in 'nulls are not equal' I used an = instead of is null or is not null here to emphasize the fact that two nulls cannot be compared.
Coming to UNION, UNION is supposed to eliminate duplicate values. I was expecting the below code to return two rows each with null since two null values are not equal, but I get only one null in the result set.
(select null as Col1)
union
(select null as Col1)
Why does SQL's interpretation of 'null as an unknown value' change in above two statements?
NULL is not comparable, but SQL generally does have the concept of "IS DISTINCT FROM"
SQL Server has a Connect item for it
1 IS DISTINCT FROM NULL = true
1 = null is false
For completeness, NULL IS DISTINCT FROM NULL = false
I would guess that DISTINCT and UNION use IS DISTINCT FROM (as Pரதீப் mentioned above)
Now, SQL Server does have IS DISTINCT FROM in INTERSECT and EXCEPT
DECLARE #t1 TABLE (t1col INT);
INSERT #t1 VALUES (1), (NULL), (2), (3), (3), (5), (5);
DECLARE #t2 TABLE (t2col INT);
INSERT #t2 VALUES (1), (NULL), (3), (4);
SELECT DISTINCT 't1 EXISTS t2', *
FROM #t1 t1 WHERE EXISTS (SELECT * FROM #t2 t2 WHERE t1.t1col = t2.t2col);
t1 EXISTS t2 1
t1 EXISTS t2 3
t1 EXISTS t2 3
SELECT DISTINCT 't1 INTERSECT t2', *
FROM #t1 INTERSECT SELECT 't1 INTERSECT t2', * FROM #t2;
t1 INTERSECT t2 NULL
t1 INTERSECT t2 1
t1 INTERSECT t2 3
INTERSECT and EXCEPT also remove duplicates because they do a semi-join
EXISTS is an anti-join BTW
For completeness
SELECT 't1 EXISTS t2', *
FROM #t1 t1 WHERE NOT EXISTS (SELECT * FROM #t2 t2 WHERE t1.t1col = t2.t2col);
t1 EXISTS t2 NULL
t1 EXISTS t2 2
t1 EXISTS t2 5
t1 EXISTS t2 5
SELECT 't1 EXCEPT t2', *
FROM #t1 EXCEPT SELECT 't1 EXCEPT t2', * FROM #t2;
t1 EXCEPT t2 2
t1 EXCEPT t2 5
Example taken from my answer Why does EXCEPT exist in T-SQL? with added NULLs
UNION is basically SELECT DISTINCT, so it would be eliminating duplicate NULL values, but it's not the same as Equal operation.
Using UNION ALL would give you all records including duplicating NULLs.
As for the first part of you question. NULL really equals NULL, but not with "=". This would give you result you expect:
if null IS null
select 'nulls are equal'
else
select 'nulls are not equal'
This is also helpful when dealing with nulls.
Try UNION ALL to retain everything in both sets without removing duplicates.

MSSQL SP: Select all rows from one table using IDs from another

Perhaps quite a simple question, that seems to have a rather complicated answer that I have not been able to dig out.
Im using an SQL-server 2012.
I have these two statements, that selects all my data based on a parameter, and then also selects up to five rows of data (which means no joins) from another table based on the IDs gotten from the first select.
SELECT * FROM TBL1 WHERE XXX
SELECT * FROM TBL2
WHERE TBL1_ID IN (SELECT ID FROM TBL1 WHERE XXX)
It seems very redundant to me, that I basicly have to repeat my TBL1 select in my TBL2, and instead I would like to know if I can select from TBL2 using the ID's from the * data I got from TBL1.
I am fully aware that this will most likely result in two resultsets that dont necessarily correlate, but I can generally use PHP array-manipulation to fix this so its not that big of a deal.
You also use EXISTS
SELECT * FROM TBL2
WHERE EXISTS (SELECT 1 FROM TBL1 WHERE TBL1.ID = TBL2.TBL1_ID AND XXX)
Using IN:
Declare #T1 table (ID INT , Value VARCHAR(50) );
Declare #T2 table (ID INT);
INSERT INTO #T1 Values (1,'First') , (2,'Second');
INSERT INTO #T2 Values (1),(3);
SELECT * FROM #T1 WHERE ID IN (SELECT ID FROM #T2);
Resault :
ID Value
----------- ------------------------------------------------------------------------------
1 First
Using INNER JOIN :
SELECT T1.ID , T1.Value FROM #T1 T1 INNER JOIN #T2 T2 ON T1.ID = T2.ID;
Resault:
ID Value
----------- ------------------------------------------------------------------------------
1 First
Using LEFT JOIN :
SELECT T1.ID , T1.Value FROM #T1 T1 LEFT JOIN #T2 T2 ON T1.ID = T2.ID
WHERE T2.ID IS NOT NULL;
Resault :
ID Value
----------- -------------------------------------------------------------------------------
1 First

SQL joined table pivot without aggregate

I have two tables:
Table1
ID TYPE
1 ABC1
2 ABC2
3 ABC3
Table2
ID Data
1 100
1 101
2 10
2 90
And I want the results to look like this:
ID Data1 Data2
1 100 101
2 10 90
But I'm having a total mare with my attempts at creating the pivot. So far I have:
With Inital_Data As (
Select
A.ID,
B.Data As Data1,
B.Data As Data2
From
Table1 A join
Table2 B on
A.ID = B.ID
)
Select *
From
Initial_Data
PIVOT
(Max(ID) FOR Data IN (Data1,Data2)) p
I know this is rubbish but so far even the logic of what I'm trying to achieve is escaping me, let alone the syntax! Can anyone give me a guiding hand?
Pivot with more than one column needs some tricks, I prefer the XML concatenation. First I take all values for each ID in only one XML, then you can take these values one by one:
Just paste this into an empty query window and execute. Adapt for your needs
EDIT: Includes column Type from TABLE1 as Caption for ID...
DECLARE #Table1 TABLE(ID INT,[TYPE] VARCHAR(10));
INSERT INTO #Table1 VALUES
(1,'ABC1')
,(2,'ABC2')
,(3,'ABC3');
DECLARE #Table2 TABLE(ID INT,DATA INT);
INSERT INTO #Table2 VALUES
(1,100)
,(1,101)
,(2,10)
,(2,90);
WITH DistinctIDs AS
(
SELECT DISTINCT tbl2.ID,tbl1.[TYPE]
FROM #Table2 AS tbl2
INNER JOIN #Table1 AS tbl1 ON tbl1.ID=tbl2.ID
)
SELECT ID,[TYPE]
,concatXML.x.value('/root[1]/item[1]/#data','int') AS Data1
,concatXML.x.value('/root[1]/item[2]/#data','int') AS Data2
FROM DistinctIDs AS dIDs
CROSS APPLY
(
SELECT ID AS [#id],DATA AS [#data]
FROM #Table2 AS tbl WHERE tbl.ID=dIDs.ID
FOR XML PATH('item'), ROOT('root'),TYPE
) AS concatXML(x)

Resources