Joining Non-Distinct and Distinct Tables - sql

Using MS SQL SERVER 2008
I have the following scenario below:
===================
| Table A |
===================
|id |desc |code
| 1 |ballpen |1010
| 2 |pencil |1010
| 3 |stabilo |1010
| 4 |pins |1011
| 5 |clips |1011
===================
| Table B |
===================
| id |code
| 1010 |AAA
| 1011 |BBB
| 1013 |CCC
What I need to accomplish is something below:
===================
| Table C |
===================
|id |desc |code |code 2
| 1 |ballpen |1010 |AAA
| 2 |pencil |1010 |AAA
| 3 |stabilo |1010 |AAA
| 4 |pins |1011 |BBB
| 5 |clips |1011 |BBB
Here's what I have so far, unfortunately the LEFT JOIN is causing the final query output to bloat
select *
from table a
left join table b on a.code = b.id
Result:
========
Table D
========
|id |desc |code |code2
|1 |ballpen |1010 |AAA
|1 |ballpen |1010 |AAA
|1 |ballpen |1010 |AAA
|2 |pencil |1010 |AAA
|2 |pencil |1010 |AAA
|2 |pencil |1010 |AAA
|3 |stabilo |1010 |AAA
|3 |stabilo |1010 |AAA
|3 |stabilo |1010 |AAA
|4 |pins |1011 |BBB
|4 |pins |1011 |BBB
|5 |clips |1011 |BBB
|5 |clips |1011 |BBB

Note:I think u have used same table name in join.let try using different table name
I have used Left Join it works..
create table #master
(
ID int,
descs varchar(15),
code int
)
create table #codes
(
ids int,
codes varchar(15)
)
insert into #master values(1,'ballpen',1010)
insert into #master values(2,'pencil',1010)
insert into #master values(3,'stabilo',1010)
insert into #master values(4,'pins',1011)
insert into #master values(5,'Clips',1011)
insert into #codes values(1010,'AAA')
insert into #codes values(1011,'BBB')
insert into #codes values(1013,'CCC')
select ID,descs,code,codes from #master a
left join #codes b
on a.code = b.ids
Output:
ID descs code codes
1 ballpen 1010 AAA
2 pencil 1010 AAA
3 stabilo 1010 AAA
4 pins 1011 BBB
5 Clips 1011 BBB
In case left join not works for you use Inner join:
select ID,descs,code,codes from #master a,#codes b
where a.code=b.ids

You should try a inner Join
SELECT
distinct a.id,a.desc1,a.code,b.code as code2
from a
inner join b
on a.code = b.id

I guess that table B contains not unique code, so you need to do distinct of the selected dataset
here the test:
--Create temp tables for data sample
--table A - unique ID
DECLARE #tableA AS TABLE
(
id INT ,
[DESC] VARCHAR(20) ,
code BIGINT
)
INSERT INTO #tableA
( id, [DESC], code )
VALUES ( 1, 'ballpen', 1010 ),
( 2, 'pencil', 1010 ),
( 3, 'stabilo', 1010 ),
( 4, 'pins', 1011 ),
( 5, 'clips', 1011 )
--table B not unique code
DECLARE #tableB AS TABLE ( id INT, code VARCHAR(10) )
INSERT INTO #tableB
( id, code )
VALUES ( 1010, 'AAA' ),
( 1011, 'BBB' ),
( 1013, 'CCC' ),
( 1010, 'AAA' ),
( 1011, 'BBB' ),
( 1013, 'CCC' ),
( 1010, 'AAA' ),
( 1011, 'BBB' ),
( 1013, 'CCC' )
------------------------------------------------------------------------------------------
--1 variant of the final query
SELECT DISTINCT
a.id ,
a.[DESC] ,
a.code ,
b.code AS [code 2]
FROM #tableA AS a
LEFT JOIN #tableB AS b ON a.code = b.id
--2 variant of the final query
SELECT *
FROM ( SELECT DISTINCT
a.id ,
a.[DESC] ,
a.code ,
b.code AS [code 2] ,
ROW_NUMBER() OVER ( PARTITION BY a.id ORDER BY a.id ) AS RN
FROM #tableA AS a
LEFT JOIN #tableB AS b ON a.code = b.id
) AS t
WHERE rn = 1
--3 variant of the final query
;WITH cte AS
( SELECT DISTINCT
a.id ,
a.[DESC] ,
a.code ,
b.code AS [code 2] ,
ROW_NUMBER() OVER ( PARTITION BY a.id ORDER BY a.id ) AS RN
FROM #tableA AS a
LEFT JOIN #tableB AS b ON a.code = b.id
)
SELECT *
FROM cte
WHERE rn = 1
--4 variant of the final query
SELECT TOP 1 WITH TIES
a.id ,
a.[DESC] ,
a.code ,
b.code AS [code 2]
FROM #tableA AS a
LEFT JOIN #tableB AS b ON a.code = b.id
ORDER BY ROW_NUMBER() OVER ( PARTITION BY a.id ORDER BY a.id )
below screenshot of the result:

Related

Recursive CTE (T-SQL) Returns Un-expected Result

I've been staring at this code for WAY too long, trying to figure out why my final query returns unexpected results.
Any help would be much appreciated. Thanks in advance.
Given the following code (running on SQL Server 2008 R2):
USE tempdb;
DECLARE #emp--loyee
TABLE (
EmployeeID int NOT NULL
,EmployeeName nvarchar(50) NOT NULL
PRIMARY KEY(EmployeeID)
)
INSERT INTO #emp
SELECT 1,'Fred'
UNION
SELECT 2,'Mary'
UNION
SELECT 3,'Joe'
UNION
SELECT 4,'Bill'
DECLARE #grp TABLE (
GroupID int NOT NULL
,GroupName nvarchar(50)
PRIMARY KEY(GroupID)
)
INSERT INTO #grp
SELECT 1,'Group 1'
UNION
SELECT 2,'Group 2'
UNION
SELECT 3,'Group 3'
DECLARE #empgrp TABLE (
EmployeeID int NOT NULL
,GroupID int NOT NULL
PRIMARY KEY (EmployeeID,GroupID)
)
INSERT INTO #empgrp
SELECT 1,1
UNION
SELECT 2,1
UNION
SELECT 3,1
UNION
SELECT 4,2
DECLARE #grpgrp TABLE (
GroupID int NOT NULL
,ParentGroupID int
,UNIQUE CLUSTERED(GroupID,ParentGroupID)
)
INSERT INTO #grpgrp
SELECT 1,2
UNION
SELECT 2,3;
WITH AllEmpGroups (EmployeeID,GroupID,RootGroupID)
AS
(
SELECT CAST(NULL as int) as EmployeeID,pgrp.GroupID,pgrp.ParentGroupID
FROM #grpgrp pgrp LEFT JOIN #grpgrp ggrp
ON pgrp.ParentGroupID = ggrp.GroupID
UNION ALL
SELECT e.EmployeeID,eg.GroupID,aeg.RootGroupID
FROM #emp e JOIN #empgrp eg
ON e.EmployeeID = eg.EmployeeID
JOIN #grpgrp ggrp
ON eg.GroupID = ggrp.GroupID
JOIN AllEmpGroups aeg
ON aeg.GroupID = ggrp.ParentGroupID
)
SELECT EmployeeID,GroupID,RootGroupID
FROM AllEmpGroups
What I get is:
+------------+---------+-------------+
| EmployeeID | GroupID | RootGroupID |
+------------+---------+-------------+
| NULL | 1 | 2 |
| NULL | 2 | 3 |
| 1 | 1 | 3 |
| 2 | 1 | 3 |
| 3 | 1 | 3 |
+------------+---------+-------------+
What I would expect/want to get is this:
+------------+---------+-------------+
| EmployeeID | GroupID | RootGroupID |
+------------+---------+-------------+
| NULL | 1 | 2 |
| NULL | 2 | 3 |
| 4 | 2 | 3 |
| 1 | 1 | 3 |
| 2 | 1 | 3 |
| 3 | 1 | 3 |
+------------+---------+-------------+
Bottom line, I want the full recursive stack of all employees beneath a given root group(s), with the root group id on every row.
What am I missing?
First:
You need a row for the root node in #grpgrp with values 3, null
The anchor (part before the union all) of your recursive cte needs to be the root node (3, null) for ancestor first recursion.
...
INSERT INTO #grpgrp
SELECT 1,2
UNION all
SELECT 2,3
UNION all
select 3, null;
WITH AllEmpGroups (EmployeeID,GroupID,RootGroupID)
AS
(
SELECT CAST(NULL as int) as EmployeeID,pgrp.GroupID, ParentGroupID = pgrp.GroupID
FROM #grpgrp pgrp LEFT JOIN #grpgrp ggrp
ON pgrp.ParentGroupID = ggrp.GroupID
where pgrp.ParentGroupId is null
UNION ALL
SELECT e.EmployeeID,eg.GroupID,aeg.RootGroupID
FROM #emp e JOIN #empgrp eg
ON e.EmployeeID = eg.EmployeeID
JOIN #grpgrp ggrp
ON eg.GroupID = ggrp.GroupID
JOIN AllEmpGroups aeg
ON aeg.GroupID = ggrp.ParentGroupID
)
SELECT EmployeeID,GroupID,RootGroupID
FROM AllEmpGroups
rextester demo: http://rextester.com/CBWY80387
returns:
+------------+---------+-------------+
| EmployeeID | GroupID | RootGroupID |
+------------+---------+-------------+
| NULL | 3 | 3 |
| 4 | 2 | 3 |
| 1 | 1 | 3 |
| 2 | 1 | 3 |
| 3 | 1 | 3 |
+------------+---------+-------------+
Beyond that, I would build the groups hierarchy first, then join the employees like so:
WITH AllEmpGroups (GroupID,ParentGroupID,RootGroupID)
AS
(
SELECT pgrp.GroupID, pgrp.ParentGroupID, RootGroupId = GroupID
FROM #grpgrp pgrp
where pgrp.ParentGroupId is null
UNION ALL
SELECT ggrp.GroupID,ggrp.ParentGroupID,aeg.RootGroupID
FROM #grpgrp ggrp
inner JOIN AllEmpGroups aeg
ON aeg.GroupID = ggrp.ParentGroupID
)
SELECT eg.EmployeeID,aeg.*
FROM AllEmpGroups aeg
left JOIN #empgrp eg
ON eg.GroupID = aeg.GroupID
rextester demo: http://rextester.com/FAK76354
returns:
+------------+---------+---------------+-------------+
| EmployeeID | GroupID | ParentGroupID | RootGroupID |
+------------+---------+---------------+-------------+
| NULL | 3 | NULL | 3 |
| 4 | 2 | 3 | 3 |
| 1 | 1 | 2 | 3 |
| 2 | 1 | 2 | 3 |
| 3 | 1 | 2 | 3 |
+------------+---------+---------------+-------------+
Start with
WITH AllGroups (RootGroupID,GroupID,ParentGroupID, level)
AS
(
SELECT GroupID RootGroupID, GroupID, Cast(NULL as int) ParentGroupID, 0 level
FROM #grp g
WHERE NOT EXISTS (SELECT 1 FROM #grpgrp gg WHERE gg.GroupID = g.GroupID)
UNION ALL
SELECT ag.RootGroupID, gg.GroupID, gg.ParentGroupID, level+1
FROM #grpgrp gg
JOIN AllGroups ag
ON ag.GroupID = gg.ParentGroupID
)
SELECT EmployeeID, ag.GroupID, ParentGroupID, RootGroupID
FROM AllGroups ag
LEFT JOIN #empgrp eg ON eg.GroupID = ag.GroupID
ORDER BY RootGroupID, level, ParentGroupID, GroupID;
Not sure why you need the row:
| NULL | 2 | 3 |

Insert new colum with previous rows information

I have this table:
Id |Name |ParentId
1 |John |Null
2 |Oscar |1
3 |Peter |2
4 |Abbey |3
5 |Adrian |4
6 |Barbara |5
and i want to make a select that will give me a new column that gets the previous Name with by the parentId to make a listName (Order by ParentID).
the final result in this example would be this:
Id |Name |ParentId | List
1 |John |Null | John
2 |Oscar |1 | John-Oscar
3 |Peter |2 | John-Oscar-Peter
4 |Abbey |3 | John-Oscar-Peter-Abbey
5 |Adrian |4 | John-Oscar-Peter-Abbey-Adrian
6 |Barbara |5 | John-Oscar-Peter-Abbey-Adrian-Barbara
Thnks for all the help!
You can use a recursive CTE to produce the desired result:
declare #t table (Id int, Name varchar(20), ParentId int)
insert #t values
( 1 ,'John' ,Null ),
( 2 ,'Oscar' ,1 ),
( 3 ,'Peter' ,2 ),
( 4 ,'Abbey' ,3 ),
( 5 ,'Adrian' ,4 ),
( 6 ,'Barbara' ,5 )
;with x as (
select *, cast(name as varchar(1000)) as list from #t where parentid is null
union all
select t.id, t.name, t.parentid, cast(x.list+'-'+t.name as varchar(1000)) from #t t join x on t.parentid = x.id
)
select * from x
This also works for multiple roots, of course.
This is same as concatenate columns to rows
select id,name,pid,
stuff((select '-'+name from yourtable n2 where n2.id<=n1.id for xml path('')),1,1,'') b
from yourtable n1

Join Vertical & Horizontal table in SQL Server using Pivot

I want to join two tables and combine into one but problem is one table is in Horizontal Format and other in Vertical format.
below is the table structure and join will be on Employeeid:
Table 1 : EmpDetail
ID | CODE | Name
-- |--------| ---
1 | 1008M | ABC
2 | 1039E | XYZ
3 | 1040E | TYS
Table 2 : EmpCustomeDetail
EmpID | FiledName | FieldValue
-- |-------- | ---
1 | FlD1 | temp1
1 | FlD2 | temp2
1 | FlD3 | temp3
2 | FlD1 | temp1
3 | FLD4 | temp6
Desired Output Required :
EmpID | Code | Name | Fld1 | Fld2 | Fld3 | Fld4
-- |---- | ------| --- | ---- |---- |----
1 | 1008M | ABC | temp1 | temp2 | temp3 | null
2 | 1039E | XYZ | temp1 | null | null | null
3 | 1040E | TYS | null | null | null | temp6
I had tried using Pivot Query but it is not giving exact output which i requried
Below is the query so far i have tried
SELECT A.*
FROM (
SELECT
e.Id,
e.code,
e.Fname,
FROM EmpDetail e
LEFT JOIN (
SELECT *
FROM (
SELECT
d.CustomeFieldName
, c.ComboValue
, d.EmployeeId
FROM EmpCustomeDetail d
) src
PIVOT (
MAX(FieldValue)
) src2
) c ON e.Id = c.EmployeeId
) A
Here are two statements:
The first is a simple PIVOT. You can use it, in case you know all Fieldnames (btw: there's a typo in your sample) in advance.
The second is roughly the same statement, but the column names are taken dynamically. This will work with (almost) any count and with different namings.
First a mock-up-test-scenraio
CREATE TABLE DummyEmpDetail (ID INT,CODE VARCHAR(10),Name VARCHAR(100));
INSERT INTO DummyEmpDetail VALUES
(1,'1008M','ABC')
,(2,'1039E','XYZ')
,(3,'1040E','TYS');
CREATE TABLE DummyEmpCustomeDetail (EmpID INT,FiledName VARCHAR(100),FieldValue VARCHAR(100));
INSERT INTO DummyEmpCustomeDetail VALUES
(1,'FlD1','temp1')
,(1,'FlD2','temp2')
,(1,'FlD3','temp3')
,(2,'FlD1','temp1')
,(3,'FLD4','temp6');
--The static PIVOT statement
SELECT p.EmpID
,p.Name
,p.CODE
,p.Fld1
,p.Fld2
,p.Fld3
p,Fld4
FROM
(
SELECT e.CODE,e.Name,ec.*
FROM DummyEmpDetail AS e
INNER JOIN DummyEmpCustomeDetail AS ec ON e.ID=ec.EmpID
) AS tbl
PIVOT
(
MAX(FieldValue) FOR FiledName IN(Fld1,Fld2,Fld3,Fld4)
) AS p;
--The dynamic PIVOT statement
DECLARE #colNames VARCHAR(MAX)=
(
STUFF
(
(
SELECT DISTINCT ',' + QUOTENAME(FiledName) FROM DummyEmpCustomeDetail
FOR XML PATH('')
),1,1,''
)
);
DECLARE #command VARCHAR(MAX)=
'SELECT p.EmpID
,p.Name
,p.CODE
,' + #colNames +
' FROM
(
SELECT e.CODE,e.Name,ec.*
FROM DummyEmpDetail AS e
INNER JOIN DummyEmpCustomeDetail AS ec ON e.ID=ec.EmpID
) AS tbl
PIVOT
(
MAX(FieldValue) FOR FiledName IN(' + #colnames + ')
) AS p;';
EXEC (#command);
GO
DROP TABLE DummyEmpCustomeDetail;
DROP TABLE DummyEmpDetail;
Both lead to the same result...
Try like below. If values of fieldname will not be static then you should use dynamic sql.
SELECT EMPID,
CODE,
NAME,
FLD1,
FLD2,
FLD3,
FLD4
FROM EmpDetail C
JOIN (SELECT A.*
FROM EmpCustomeDetail
PIVOT ( MIN([FIELDVALUE])
FOR [FILEDNAME] IN([FLD1],
[FLD3],
[FLD2],
FLD4) )A)B
ON C.ID = B.[EMPID]
No need for sub-queries.
select e.*,FlD1,FlD2,FlD3,FlD4
from EmpDetail e
left join EmpCustomeDetail
pivot (max(FieldValue) for FiledName in (FlD1,FlD2,FlD3,FlD4)) ecd
on ecd.EmpID = e.ID
+----+-------+------+-------+-------+-------+-------+
| ID | CODE | Name | FlD1 | FlD2 | FlD3 | FlD4 |
+----+-------+------+-------+-------+-------+-------+
| 1 | 1008M | ABC | temp1 | temp2 | temp3 | NULL |
+----+-------+------+-------+-------+-------+-------+
| 2 | 1039E | XYZ | temp1 | NULL | NULL | NULL |
+----+-------+------+-------+-------+-------+-------+
| 3 | 1040E | TYS | NULL | NULL | NULL | temp6 |
+----+-------+------+-------+-------+-------+-------+

get parents (and their parents,...) from table with self relationship in SQL Server

I have been breaking my head over this, but without any succes... I have following self-reverencing table (Table A):
ID |EmployeeID | ParentID | Level |
1 |11 | null | A |
2 |12 | 11 | B |
3 |13 | 12 | C |
4 |14 | 12 | C |
(it's not well build, but we can't change that anymore)
I need to create a view that gives following result:
ID | EmployeeID | Level | LevelA | LevelB | LevelC | LevelD
1 | 11 | A | 11 | null | null | null
2 | 12 | B | 11 | 12 | null | null
3 | 13 | C | 11 | 12 | 13 | null
4 | 14 | C | 11 | 12 | 14 | null
ID, EmployeeID and Level come directly from Table A.
Level A - D gives the parent of that EmployeeID and the next parents in hierarchy. If the Level of the Employee is C, you can say it is a C-level employee so his ID is in column LevelC. His Parent is a B-Level employee, so his ID comes in column LevelB. His patent is a A-level employee (which is the highest rank) and his ID comes in column LevelA.
The empty levels just stay null.
Any ideas/suggestions?
I think you need something like:
SELECT A.ID, A.EMPLOYEEID, A.LEVEL, PT.A, PT.B, PT.C, PT.D
FROM TABLEA A
INNER JOIN
(
SELECT * FROM
(SELECT ID, EMPLOYEEID, LEVEL FROM TABLEA) AS SOURCETABLE
PIVOT (
MAX([EMPLOYEEID])
FOR LEVEL IN ([A], [B], [C], [D])) AS PIVOTTABLE
) AS PT
ON A.ID = PT.ID
This code Works as long as you have four columns, but you'll see null values in the columns not matched by the pivot.
Hope it helps.
Use Common Table Expression (CTE)
With MyCTE
As (SELECT EmployeeID, ParentID, Level
FROM tableA
WHERE ParentID IS NULL
UNION ALL
SELECT EmployeeID, ParentID, Level
FROM tableA a join MyCTE c
ON c.EmployeeID = a.ParentID
WHERE a.ParentID IS NOT NULL )
SELECT * FROM MyCTE
You really don't even need the Level column in the table
With MyCTE
As (SELECT EmployeeID, ParentID, 1 Level
FROM tableA
WHERE ParentID IS NULL
UNION ALL
SELECT a.EmployeeID, a.ParentID, Level + 1 Level
FROM tableA a join MyCTE c
ON c.EmployeeID = a.ParentID
WHERE a.ParentID IS NOT NULL )
SELECT * FROM MyCTE
to just add the extra columns, you can use Pivot,

Find the common ancestor in a tree-structured table

I have a table structure like this (there are actually more levels):
------------------------------------------
|region1|region2|region3|region4|postcode|
|-------|-------|-------|-------|--------|
|a |x |i | |1 |
|a |y |i | |2 |
|a |y |j | |2 |
|a |z |k | |3 |
|b |u |m | |4 |
|b | |n | |4 |
|c | | | |5 |
|c |q | | |6 |
------------------------------------------
So for example, a => x => i and a => y => i are different places but both are in the same region1 a.
I want to know which region each postcode can cover.
For example, code 2 covers areas a => y => i and a => y => j, so the common ancestor for those are a => y.
Here is the desired output of the query run on the example:
------------------------------------------
|postcode|region1|region2|region3|region4|
|--------|-------|-------|-------|-------|
|1 |a |x |i | |
|2 |a |y | | |
|3 |a |z |k | |
|4 |b | | | |
|5 |c | | | |
|6 |c |q | | |
------------------------------------------
I don't really know how to attack this problem. I thought about partitioning by the postcode, but that still leaves the problem of finding the common ancestor within each partition...
This is a really messy solution, but it does seem to give the correct answer. It would no doubt need quite a bit of work to fit your actual requirement, but maybe this could help point you in some sort of direction!
-- Setup a test table
DECLARE #tbl AS TABLE(R1 NVARCHAR(10), R2 NVARCHAR(10), R3 NVARCHAR(10), R4 NVARCHAR(10), PC NVARCHAR(10));
INSERT INTO #tbl(R1,R2,R3,R4,PC) VALUES ('a','x','i',NULL,'1');
INSERT INTO #tbl(R1,R2,R3,R4,PC) VALUES ('a','y','i',NULL,'2');
INSERT INTO #tbl(R1,R2,R3,R4,PC) VALUES ('a','y','j',NULL,'2');
INSERT INTO #tbl(R1,R2,R3,R4,PC) VALUES ('a','z','k',NULL,'3');
INSERT INTO #tbl(R1,R2,R3,R4,PC) VALUES ('b','u','m',NULL,'4');
INSERT INTO #tbl(R1,R2,R3,R4,PC) VALUES ('b',NULL,'n',NULL,'4');
INSERT INTO #tbl(R1,R2,R3,R4,PC) VALUES ('c',NULL,NULL,NULL,'5');
INSERT INTO #tbl(R1,R2,R3,R4,PC) VALUES ('c','q',NULL,NULL,'6');
-- Calculate the result:
SELECT
PC,
CASE WHEN LVL1 = 1 THEN R1 ELSE NULL END AS R1,
CASE WHEN LVL2 = 1 THEN R2 ELSE NULL END AS R2,
CASE WHEN LVL3 = 1 THEN R3 ELSE NULL END AS R3,
CASE WHEN LVL4 = 1 THEN R4 ELSE NULL END AS R4
FROM
(
SELECT
PC,
MAX(R1) AS R1,
MAX(R2) AS R2,
MAX(R3) AS R3,
MAX(R4) AS R4,
COUNT(DISTINCT ISNULL(R1,'.')) AS LVL1,
COUNT(DISTINCT ISNULL(R1,'.') + ISNULL(R2,'.')) AS LVL2,
COUNT(DISTINCT ISNULL(R1,'.') + ISNULL(R2,'.') + ISNULL(R3,'.')) AS LVL3,
COUNT(DISTINCT ISNULL(R1,'.') + ISNULL(R2,'.') + ISNULL(R3,'.') + ISNULL(R4,'.')) AS LVL4
FROM #tbl
GROUP BY PC
) A
The end result matches the table in the question.
This question rather intrigued me and I came up with an alternative, which you might find useful:
-- Setup test table
DECLARE #InputTable TABLE (region1 varchar(2), region2 varchar(2), region3 varchar(2), region4 varchar(2), postcode varchar(2))
INSERT INTO #InputTable (region1, region2, region3, region4, postcode)
SELECT 'a','x','i',null,'1'
UNION ALL SELECT 'a','y','i',NULL,'2'
UNION ALL SELECT 'a','y','j',NULL,'2'
UNION ALL SELECT 'a','z','k',NULL,'3'
UNION ALL SELECT 'b','u','m',NULL,'4'
UNION ALL SELECT 'b',NULL,'n',NULL,'4'
UNION ALL SELECT 'c',NULL,NULL,NULL,'5'
UNION ALL SELECT 'c','q',NULL,NULL,'6'
-- Find the common ancestors
;with totals as (
select postcode, count(*) as postcodeCount from #InputTable group by postcode
)
, region4group as (
select postcode, region1, region2, region3, region4 from #InputTable in1
group by postcode, region1, region2, region3, region4 having count(*)=(select postCodeCount from totals where totals.postcode=in1.postcode)
)
, region3group as (
select * from region4group
union
select in1.postcode, in1.region1, in1.region2, in1.region3, null from #InputTable in1
left outer join region4group on region4group.postcode=in1.postcode
where region4group.postcode is null
group by in1.postcode, in1.region1, in1.region2, in1.region3
having count(*)=(select postCodeCount from totals where totals.postcode=in1.postcode)
)
, region2group as (
select * from region3group
union
select in1.postcode, in1.region1, in1.region2, null, null from #InputTable in1
left outer join region3group on region3group.postcode=in1.postcode
where region3group.postcode is null
group by in1.postcode, in1.region1, in1.region2
having count(*)=(select postCodeCount from totals where totals.postcode=in1.postcode)
)
, commonancestors as (
select * from region2group
union
select in1.postcode, in1.region1, null, null, null from #InputTable in1
left outer join region2group on region2group.postcode=in1.postcode
where region2group.postcode is null
group by in1.postcode, in1.region1
having count(*)=(select postCodeCount from totals where totals.postcode=in1.postcode)
)
select * from commonancestors