Displaying multiple select in a single cell - sql

Please help me to solve the following issue .
consider i have two tables in a Database
1.employee 2.Details
In employee table data will be
eid ename level
1 x 9th
2 y 10th
In Address Table data will be
AId eid location Adreess_type
1 1 india permananet
2 1 US Temporary
3 2 Japan permananet
4 2 China Temporary
I need output in the below format
eid ename fulllocation
1 X INDIA -US
2 y Japan-CHINA

Try this:
SELECT
e.eid,
e.name,
GROUP_CONCAT(a.location SEPARATOR '-') AS fulllocation
FROM
employee as e
INNER JOIN address as a
ON e.eid = a.eid
GROUP BY
e.eid

select employee.eid, employee.ename, t.fulllocation
from employee
inner join (select eid, group_concat(location SEPARATOR '-') as fulllocation from Address group by eid) t
on employee.eid = t.eid
Consider that GROUP_CONCAT have some limitations, what is this and how can change (if needed) it? please check documentation for this.

DECLARE #t1 TABLE
(
eid int NOT NULL,
ename varchar(50),
level varchar(50)
)
DECLARE #t2 TABLE
(
aid int NOT NULL,
eid int,
location varchar(50),
address_type varchar(50)
)
INSERT INTO #t1 SELECT 1, 'x', '9th'
INSERT INTO #t1 SELECT 2, 'y', '10th'
INSERT INTO #t2 SELECT 1, 1, 'india', 'permanent'
INSERT INTO #t2 SELECT 2, 1, 'US', 'temporary'
INSERT INTO #t2 SELECT 3, 2, 'Japan', 'permanent'
INSERT INTO #t2 SELECT 4, 2, 'China', 'temporary'
SELECT * FROM #t1
SELECT * FROM #t2
SELECT t1.eid, t1.ename, t2.fullLocation
FROM #t1 AS t1
INNER JOIN (
SELECT eid, COUNT(*) AS noofrecs
, fullLocation = LTRIM(RTRIM(ISNULL(STUFF(
(
SELECT DISTINCT '-' + CAST(t2.location as nvarchar(max))
FROM #t2 t2
WHERE t1.eid = t2.eid
FOR XML PATH (''), TYPE).value('.', 'nvarchar(max)'
), 1, 1, ''), '')))
FROM #t2 as t1
GROUP BY eid
) AS t2
ON t1.eid = t2.eid

DECLARE #t1 TABLE
(
eid int NOT NULL,
ename varchar(50),
level varchar(50)
)
DECLARE #t2 TABLE
(
aid int NOT NULL,
eid int,
location varchar(50),
address_type varchar(50)
)
INSERT INTO #t1 SELECT 1, 'x', '9th'
INSERT INTO #t1 SELECT 2, 'y', '10th'
INSERT INTO #t2 SELECT 1, 1, 'india', 'permanent'
INSERT INTO #t2 SELECT 2, 1, 'US', 'temporary'
INSERT INTO #t2 SELECT 3, 2, 'Japan', 'permanent'
INSERT INTO #t2 SELECT 4, 2, 'China', 'temporary'
SELECT * FROM #t1
SELECT * FROM #t2
SELECT b.eid,b.ename
, STUFF((SELECT '_ ' + a.location FROM #t2 A
Where A.eid=B.eid FOR XML PATH('')),1,1,'') As fulllocation
From #t1 B
Group By b.eid,b.ename

In order to preserve the order of the locations, you could work along
SELECT
e.eid
, e.ename
, CONCAT_WS('-', p.location, t.location) AS fulllocation
FROM Employee e
JOIN Address p
ON e.eid = p.eid
AND p.address_type = 'permananet'
JOIN Address t
ON e.eid = t.eid
AND t.address_type = 'Temporary'
;
See it in action: SQL Fiddle.
Please comment if and as this requrires adjustment / further detail.

Related

Want to compare 4 different columns with the result of CTE

I have created a CTE (common table Expression) as follows:
DECLARE #N VARCHAR(100)
WITH CAT_NAM AS (
SELECT ID, NAME
FROM TABLE1
WHERE YEAR(DATE) = YEAR(GETDATE())
)
SELECT #N = STUFF((
SELECT ','''+ NAME+''''
FROM CAT_NAM
WHERE ID IN (20,23,25,30,37)
FOR XML PATH ('')
),1,1,'')
The result of above CTE is 'A','B','C','D','F'
Now I need to check 4 different columns CAT_NAM_1,CAT_NAM_2,CAT_NAM_3,CAT_NAM_4 in the result of CTE and form it as one column like follow:
Select
case when CAT_NAM_1 in (#N) then CAT_NAM_1
when CAT_NAM_2 in (#N) then CAT_NAM_2
when CAT_NAM_3 in (#N) then CAT_NAM_3
when CAT_NAM_4 in (#N) then CAT_NAM_4
end as CAT
from table2
When I'm trying to do the above getting error please help me to do.
If my approach is wrong help me with right one.
I am not exactly sure what you are trying to do, but if I understand the following script shows one possible technique. I have created some table variables to mimic the data you presented and then wrote a SELECT statement to do what I think you asked (but I am not sure).
DECLARE #TABLE1 AS TABLE (
ID INT NOT NULL,
[NAME] VARCHAR(10) NOT NULL,
[DATE] DATE NOT NULL
);
INSERT INTO #TABLE1(ID,[NAME],[DATE])
VALUES (20, 'A', '2021-01-01'), (23, 'B', '2021-02-01'),
(25, 'C', '2021-03-01'),(30, 'D', '2021-04-01'),
(37, 'E', '2021-05-01'),(40, 'F', '2021-06-01');
DECLARE #TABLE2 AS TABLE (
ID INT NOT NULL,
CAT_NAM_1 VARCHAR(10) NULL,
CAT_NAM_2 VARCHAR(10) NULL,
CAT_NAM_3 VARCHAR(10) NULL,
CAT_NAM_4 VARCHAR(10) NULL
);
INSERT INTO #TABLE2(ID,CAT_NAM_1,CAT_NAM_2,CAT_NAM_3,CAT_NAM_4)
VALUES (1,'A',NULL,NULL,NULL),(2,NULL,'B',NULL,NULL);
;WITH CAT_NAM AS (
SELECT ID, [NAME]
FROM #TABLE1
WHERE YEAR([DATE]) = YEAR(GETDATE())
AND ID IN (20,23,25,30,37,40)
)
SELECT CASE
WHEN EXISTS(SELECT 1 FROM CAT_NAM WHERE CAT_NAM.[NAME] = CAT_NAM_1) THEN CAT_NAM_1
WHEN EXISTS(SELECT 1 FROM CAT_NAM WHERE CAT_NAM.[NAME] = CAT_NAM_2) THEN CAT_NAM_2
WHEN EXISTS(SELECT 1 FROM CAT_NAM WHERE CAT_NAM.[NAME] = CAT_NAM_3) THEN CAT_NAM_3
WHEN EXISTS(SELECT 1 FROM CAT_NAM WHERE CAT_NAM.[NAME] = CAT_NAM_4) THEN CAT_NAM_4
ELSE '?' -- not sure what you want if there is no match
END AS CAT
FROM #TABLE2;
You can do a bit of set-based logic for this
SELECT
ct.NAME
FROM table2 t2
CROSS APPLY (
SELECT v.NAME
FROM (VALUES
(t2.CAT_NAM_1),
(t2.CAT_NAM_2),
(t2.CAT_NAM_3),
(t2.CAT_NAM_4)
) v(NAME)
INTERSECT
SELECT ct.NAM
FROM CAT_NAM ct
WHERE ct.ID IN (20,23,25,30,37)
) ct;

Insert multiple row different column value

This is my existing table
In this table, each user has their own respective data according to their Status. Each of the user will surely have Status 1.
Now, there are 3 Status to be stored for every user.
Was trying to make every user to have 3 Status, by inserting new row of user copying their Status 1 data, such that:
User Ali currently only have Status 1 and its data, so need insert a new
row Ali with Status 2 and copy along the data from Status 1, again,
insert a new row Ali with Status 3 and copy along the data from
Status 1.
User John currently only have Status 1 and 2, so need insert a new
row John with Status 3 and copy along the data from Status 1.
continue same pattern with other user
Expected result:
I would use CROSS JOIN and NOT EXISTS
with data as
(
select name,
column1,
column2
from your_table
where status = 1
), cross_join_data as
(
select d1.name, t.status, d1.column1, d1.column2
from data d1
cross join
(
select 1 status
union
select 2 status
union
select 3 status
) t
where not exists (
select 1
from your_table d2
where d2.name = d1.name and
d2.status = t.status
)
)
select *
from your_table
union all
select *
from cross_join_data
dbfiddle demo
This should work
with cte as (
select
[Name], coalesce(max(iif([Status]=1, [Column1], null)), max(iif([Status]=2, [Column1], null)), max(iif([Status]=3, [Column1], null))) col1
, coalesce(max(iif([Status]=1, [Column2], null)), max(iif([Status]=2, [Column2], null)), max(iif([Status]=3, [Column2], null))) col2
from
MyTable
group by [Name]
)
--insert into MyTable
select
cte.[Name], nums.n, cte.col1, cte.col2
from
cte
cross join (values (1),(2),(3)) nums(n)
left join MyTable on cte.[Name]=MyTable.[Name] and n=MyTable.[Status]
where
MyTable.[Status] is null
This works if data is not nullable
declare #table table (name varchar(10), status int, data int);
insert into #table values
('a', 1, 2)
, ('a', 2, 5)
, ('a', 3, 7)
, ('b', 1, 5)
, ('b', 2, 6)
, ('c', 1, 3)
select stats.status as statusStats
, tn.name as nameTN
, t.status as statusData, t.name, t.data
, ISNULL(t.data, t1.data) as 'fillInData'
from (values (1),(2),(3)) as stats(status)
cross join (select distinct name from #table) tn
left join #table t
on t.status = stats.status
and t.name = tn.name
join #table t1
on t1.name = tn.name
and t1.status = 1
order by tn.name, stats.status
Here is what I would do:
CREATE TABLE #existingtable (Name VARCHAR(50), Status INT, Column1 VARCHAR (10), Column2 VARCHAR(10));
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('Ali',1,'100','90');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('John',1,'20','200');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('John',2,'80','90');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('Ming',1,'54','345');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('Mei',1,'421','123');
INSERT INTO #existingtable (Name,Status,Column1,Column2) Values('Mei',3,'24','344');
SELECT * FROM #existingtable;
WITH CTE (Name,Column1,Column2)
AS
(
SELECT DISTINCT NAME,COLUMN1,COLUMN2
FROM #existingtable
)
, CTE2 (NAME,Status,Column1,Column2)
AS
(
SELECT NAME,1 AS STATUS,COLUMN1,COLUMN2
FROM CTE
UNION
SELECT NAME,2 AS STATUS,COLUMN1,COLUMN2
FROM CTE
UNION
SELECT NAME,3 AS STATUS,COLUMN1,COLUMN2
FROM CTE
)
INSERT INTO #existingtable (Name,Status,Column1,Column2)
SELECT C.Name,C.Status,C.Column1,C.Column2
FROM CTE2 AS C
LEFT JOIN #existingtable AS E
ON C.NAME = E.Name
AND C.Status = E.Status
WHERE E.Status IS NULL
SELECT * FROM #existingtable
ORDER BY Name, status
This has 2 edits. Initial edit added a where clause to the CTE
Second edit added the values added by the OP

Rows to single cell

I would like to get the desired output marked in green
the data points for each id get put into a single cell
Basically take all the events that have happened with A and attach it in the same order
Use Stuff Function:
DECLARE #tblTest AS Table(
ID INT,
EVENT VARCHAR(5)
)
INSERT INTO #tblTest VALUES
(1,'A'),
(1,'A'),
(1,'C'),
(2,'A'),
(2,'B'),
(2,'C')
SELECT DISTINCT
T1.ID,
STUFF
(
(SELECT '' + convert(varchar(10), T2.EVENT, 120)
FROM #tblTest T2
where T1.ID = T2.ID
FOR XML PATH (''))
, 1, 0, '') AS EVENT
FROM #tblTest T1
You can use FOR XML:
SELECT DISTINCT
ID,
(SELECT [EVENT] +''
FROM YourTable
WHERE ID = y.ID
FOR XML PATH('')
) as [EVENT]
FROM YourTable y
Output:
ID EVENT
1 AABCD
2 AABBCC
You can use UDF to do so as follows:
CREATE TABLE t(
id INT,
col CHAR(1)
);
INSERT INTO t VALUES (1,'a');
INSERT INTO t VALUES (1,'b');
INSERT INTO t VALUES (1,'c');
INSERT INTO t VALUES (1,'d');
INSERT INTO t VALUES (2,'e');
INSERT INTO t VALUES (2,'f');
INSERT INTO t VALUES (3,'g');
INSERT INTO t VALUES (4,'h');
The UDF (User defined function) -
USE [t]
GO
CREATE FUNCTION dbo.ConcatenateCols(#Id INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #RtnStr VARCHAR(MAX)
SELECT #RtnStr = COALESCE(#RtnStr + '','') + col
FROM dbo.t
WHERE id = #Id AND col > ''
RETURN #RtnStr
END
GO
Finally the query and result:
SELECT id, dbo.ConcatenateCols(id) AS Cols -- UDF - ConcatenateCols(id)
FROM t GROUP BY Id
CREATE TABLE #temp(Id INt,Event Nvarchar(25))
INSERT INTO #temp
SELECT 1,
'A'
UNION ALL
SELECT 1,
'A'
UNION ALL
SELECT 1,
'B'
UNION ALL
SELECT 1,
'C'
UNION ALL
SELECT 1,
'D'
UNION ALL
SELECT 2,
'A'
UNION ALL
SELECT 2,
'A'
UNION ALL
SELECT 2,
'B'
UNION ALL
SELECT 2,
'B'
UNION ALL
SELECT 2,
'C'
UNION ALL
SELECT 2,
'C'
SELECT DISTINCT ID,
(SELECT [EVENT] +''
FROM #temp
WHERE ID = y.ID
FOR XML PATH('') ) AS [EVENT]
FROM #temp y

Help with recursive CTE query joining to a second table

My objective is to recurse through table tbl and while recursing through that table select a country abbreviation (if it exists) from another table tbl2 and append those results together which are included in the final output.
The example I'll use will come from this post
tbl2 has a Foreign Key 'tbl_id' to tbl and looks like this
INSERT INTO #tbl2( Id, Abbreviation, tbl_id )
VALUES
(100, 'EU', 1)
,(101, 'AS', 2)
,(102, 'DE', 3)
,(103, 'CN', 5)
*Note: not all the countries have abbreviations.
The trick is, I want all the countries in Asia to at least show the abbreviation of Asia which is 'AS' even if a country doesn't have an abbreviation (like India for example). If the country does have an abbreviation the result needs to look like this: China:CN,AS
I've got it partly working using a subquery, but India always returns NULL for the abbreviation. It's acting like if there isn't a full recursive path back to the abbreviation, then it returns null. Maybe the solution is to use a left outer join on the abbreviation table? I've tried for hours many different variations and the subquery is as close as I can get.
WITH abcd
AS (
-- anchor
SELECT id, [Name], ParentID,
CAST(([Name]) AS VARCHAR(1000)) AS "Path"
FROM #tbl
WHERE ParentId IS NULL
UNION ALL
--recursive member
SELECT t.id, t.[Name], t.ParentID,
CAST((a.path + '/' + t.Name + ':' +
(
select t2.abbreviation + ','
from #tbl2
where t.id = t2.id
)) AS VARCHAR(1000)) AS "Path"
FROM #tbl AS t
JOIN abcd AS a
ON t.ParentId = a.id
)
SELECT * FROM abcd
btw, I'm using sql server 2005 if that matters
Try this example, which will give you the output (1 sample row)
id Name ParentID Path abbreviation (No column name)
5 China 2 Asia/China CN,AS Asia/China:CN,AS
The TSQL being
DECLARE #tbl TABLE (
Id INT
,[Name] VARCHAR(20)
,ParentId INT
)
INSERT INTO #tbl( Id, Name, ParentId )
VALUES
(1, 'Europe', NULL)
,(2, 'Asia', NULL)
,(3, 'Germany', 1)
,(4, 'UK', 1)
,(5, 'China', 2)
,(6, 'India', 2)
,(7, 'Scotland', 4)
,(8, 'Edinburgh', 7)
,(9, 'Leith', 8)
;
DECLARE #tbl2 table (id int, abbreviation varchar(10), tbl_id int)
INSERT INTO #tbl2( Id, Abbreviation, tbl_id )
VALUES
(100, 'EU', 1)
,(101, 'AS', 2)
,(102, 'DE', 3)
,(103, 'CN', 5)
;WITH abbr AS (
SELECT a.*, isnull(b.abbreviation,'') abbreviation
FROM #tbl a
left join #tbl2 b on a.Id = b.tbl_id
), abcd AS (
-- anchor
SELECT id, [Name], ParentID,
CAST(([Name]) AS VARCHAR(1000)) [Path],
cast(abbreviation as varchar(max)) abbreviation
FROM abbr
WHERE ParentId IS NULL
UNION ALL
--recursive member
SELECT t.id, t.[Name], t.ParentID,
CAST((a.path + '/' + t.Name) AS VARCHAR(1000)) [Path],
isnull(nullif(t.abbreviation,'')+',', '') + a.abbreviation
FROM abbr AS t
JOIN abcd AS a
ON t.ParentId = a.id
)
SELECT *, [Path] + ':' + abbreviation
FROM abcd

Joining on a common table, how do you get a FULL OUTER JOIN to expand on another table?

I've scoured StackOverflow and Google for an answer to this problem.
I'm trying to create a Microsot SQL Server 2008 view. Not a stored procedure. Not a function. Just a query (i.e. a view).
I have three tables. The first table defines a common key, let's say "CompanyID". The other two tables have a sometimes-common field, let's say "EmployeeName".
I want a single table result that, when my WHERE clause says "WHERE CompanyID = 12" looks like this:
CompanyID | TableA | TableB
12 | John Doe | John Doe
12 | Betty Sue | NULL
12 | NULL | Billy Bob
I've tried a FULL OUTER JOIN that looks like this:
SELECT Company.CompanyID,
TableA.EmployeeName,
TableB.EmployeeName
FROM Company
FULL OUTER JOIN TableA ON Company.CompanyID = TableA.CompanyID
FULL OUTER JOIN TableB ON
Company.CompanyID = TableB.CompanyID AND
(TableA.EmployeeName IS NULL OR TableB.EmployeeName IS NULL OR TableB.EmployeeName = TableA.EmployeeName)
I'm only getting the NULL from one matched table, I'm not getting the expansion for the other table. In the above sample, I'm basically only getting the first and third rows and not the second.
Can someone help me create this query and show me how this is done correctly?
BTW I already have a stored procedure that looks very clean and populates an in-memory table, but that isn't what I want.
Thanks.
-- EDIT:
Here's a full-running sample of what currently doesn't work (it's missing 'someone 2' and 'someone 3'.
DECLARE #Company TABLE
(
CompanyID int
)
INSERT INTO #Company (CompanyID) VALUES (10)
INSERT INTO #Company (CompanyID) VALUES (12)
DECLARE #TableA TABLE
(
EmployeeId int,
CompanyId int,
EmployeeName varchar(30)
)
DECLARE #TableB TABLE
(
EmployeeId int,
CompanyId int,
EmployeeName varchar(30)
)
INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 1, 10, 'someone' )
--INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )
--VALUES ( 2, 12, 'someone 2' )
INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 3, 12, 'someone 3' )
INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 3, 12, 'someone 4' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 1, 10, 'someone' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 2, 12, 'someone 2' )
--INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )
--VALUES ( 3, 12, 'someone 3' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 3, 12, 'someone 4' )
SELECT Company.CompanyID,
TableA.EmployeeName,
TableB.EmployeeName
FROM #Company Company
FULL OUTER JOIN #TableA TableA ON Company.CompanyID = TableA.CompanyID
FULL OUTER JOIN #TableB TableB ON Company.CompanyID = TableB.CompanyID
WHERE
(
TableA.EmployeeName IS NULL OR TableB.EmployeeName IS NULL OR
TableB.EmployeeName = TableA.EmployeeName
)
AND Company.CompanyID = 12
Result:
CompanyID EmployeeName EmployeeName
12 someone 4 someone 4
What I want:
CompanyID EmployeeName EmployeeName
12 NULL someone 2
12 someone 3 NULL
12 someone 4 someone 4
try this:
SELECT Company.CompanyID,
TableA.EmployeeName,
TableB.EmployeeName
FROM Company
LEFT OUTER JOIN TableA ON Company.CompanyID = TableA.CompanyID
LEFT OUTER JOIN TableB ON Company.CompanyID = TableB.CompanyID
WHERE (TableA.EmployeeName IS NULL OR TableB.EmployeeName IS NULL OR TableB.EmployeeName = TableA.EmployeeName)
EDIT after OP gave test data and expected result set
try this (tables and test data from question):
DECLARE #Company TABLE (CompanyID int)
DECLARE #TableA TABLE (EmployeeId int,CompanyId int,EmployeeName varchar(30))
DECLARE #TableB TABLE (EmployeeId int,CompanyId int,EmployeeName varchar(30))
set nocount on
INSERT INTO #Company (CompanyID) VALUES (10)
INSERT INTO #Company (CompanyID) VALUES (12)
--INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )--VALUES ( 2, 12, 'someone 2' )
INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )VALUES ( 1, 10, 'someone' )
INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )VALUES ( 3, 12, 'someone 3' )
INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )VALUES ( 3, 12, 'someone 4' )
--INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )--VALUES ( 3, 12, 'someone 3' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )VALUES ( 1, 10, 'someone' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )VALUES ( 2, 12, 'someone 2' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )VALUES ( 3, 12, 'someone 4' )
set nocount off
SELECT coalesce(TableA.CompanyID,TableB.CompanyID) CompanyID,
TableA.EmployeeName,
TableB.EmployeeName
FROM #TableA TableA
FULL OUTER jOIN #TableB TableB ON TableA.CompanyID = TableB.CompanyID AND TableB.EmployeeName = TableA.EmployeeName
WHERE coalesce(TableA.CompanyID,TableB.CompanyID) = 12
OUTPUT:
CompanyID EmployeeName EmployeeName
----------- ------------------------------ ------------------------------
12 NULL someone 2
12 someone 3 NULL
12 someone 4 someone 4
(3 row(s) affected)
The FULL OUTER JOIN should be made only between TableA and TableB on companyID AND employeeName since this is the value you want filled as NULL if it exists only on one table.
Once you get this, you can do an inner join with Company to get other data from Company.
FULL OUTER JOIN Solution:
select Company.companyID, EmployeeNameA, EmployeeNameB
from (
SELECT isnull(TableA.CompanyID, TableB.CompanyID) as companyID,
TableA.EmployeeName as EmployeeNameA,
TableB.EmployeeName as EmployeeNameB
FROM #TableA TableA
FULL OUTER JOIN #TableB TableB ON TableA.EmployeeName = TableB.EmployeeName and TableA.companyID = TableB.companyID
WHERE
TableA.CompanyID = 12 or TableB.CompanyID = 12
) merged
inner join #Company Company
on merged.companyID = Company.companyID
Personally I find it difficult to think in terms of FULL OUTER JOINS. My approach on this would be: Find the distinct EmployeeNames you need in your result by making a UNION between affected tables and then use left joins to get data from both tables thus getting your NULLs when you should.
LEFT JOIN Example:
select c.companyID, a.employeeName, b.employeeName
from (
select distinct employeeName, companyID
from (
select a.employeeName, companyID
from #tableA a
union
select b.employeeName, companyID
from #tableB b
) a
) z
inner join #company c
on c.companyID = z.companyID
left join #tableA a
on z.companyID = a.companyID and z.employeeName = a.employeeName
left join #tableB b
on z.companyID = b.companyID and z.employeeName = b.employeeName
where z.companyID = 12
Try this
DECLARE #Company TABLE
(
CompanyID int
)
INSERT INTO #Company (CompanyID) VALUES (10)
INSERT INTO #Company (CompanyID) VALUES (12)
DECLARE #TableA TABLE
(
EmployeeId int,
CompanyId int,
EmployeeName varchar(30)
)
DECLARE #TableB TABLE
(
EmployeeId int,
CompanyId int,
EmployeeName varchar(30)
)
INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 1, 10, 'someone' )
--INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )
--VALUES ( 2, 12, 'someone 2' )
INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 3, 12, 'someone 3' )
INSERT INTO #TableA ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 3, 12, 'someone 4' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 1, 10, 'someone' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 2, 12, 'someone 2' )
--INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )
--VALUES ( 3, 12, 'someone 3' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 3, 12, 'someone 4' )
INSERT INTO #TableB ( EmployeeId, CompanyId, EmployeeName )
VALUES ( 3, 12, 'someone 4' )
SELECT Company.CompanyID,
A.EmployeeNameTableA,
A.EmployeeNameTAbleB
FROM #Company Company
left OUTER JOIN (select TableA.EmployeeName as EmployeeNameTableA, TableB.EmployeeName as EmployeeNameTableB ,
coalesce(TableA.CompanyID,TableB.CompanyID) as CompanyID
from #TableA TableA
FULL OUTER JOIN #TableB TableB ON TableA.CompanyID = TableB.CompanyID and TableB.EmployeeName = TableA.EmployeeName and (tablea.companyid = 12 or tableb.companyid = 12))A ON Company.CompanyID = A.CompanyID
WHERE Company.CompanyID = 12
Here is a variation on Dimitris Baltas' answer, which is closer to what I had in mind.
SELECT Company.CompanyID,
TableA.EmployeeName as EmployeeNameTableA,
TableB.EmployeeName as EmployeeNameTableB
FROM #TableA TableA
FULL OUTER JOIN #TableB TableB ON TableA.EmployeeName = TableB.EmployeeName
and TableA.companyID = TableB.companyID
INNER JOIN #Company Company ON (
Company.CompanyID = TableA.CompanyId OR Company.CompanyID = TableB.CompanyId
)
WHERE Company.CompanyID = 12
A key thing I am looking for (and this sample doesn't do this but Dimitris' might) was pre-filtering on the CompanyID so that the execution plan will not sift through all of the rows of each of the joined tables before filtering out the CompanyID. In my case, the two joined tables are extremely slow.
I think what I'll ultimately have to do is keep using sprocs.