我已经搜索了StackOverflow和Google以解决这个问题。
我正在尝试创建一个Microsot SQL Server 2008视图。不是存储过程。不是功能。只是一个查询(即一个视图)。
我有三张桌子。第一个表定义了一个公共密钥,比如说“CompanyID”。另外两个表有一个有时相同的字段,比如说“EmployeeName”。
我想要一个单独的表结果,当我的WHERE子句说“WHERE CompanyID = 12”时,如下所示:
CompanyID | TableA | TableB
12 | John Doe | John Doe
12 | Betty Sue | NULL
12 | NULL | Billy Bob
我尝试了一个看起来像这样的FULL OUTER JOIN:
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)
我只从一个匹配的表中获取NULL,我没有得到另一个表的扩展。在上面的示例中,我基本上只得到第一行和第三行而不是第二行。
有人可以帮我创建此查询并告诉我这是如何正确完成的吗?
BTW我已经有了一个非常干净的存储过程并填充了一个内存表,但这不是我想要的。
感谢。
- 编辑:
以下是目前没有工作的完整示例(它缺少'某人2'和'某人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
结果:
CompanyID EmployeeName EmployeeName
12 someone 4 someone 4
我想要的是什么:
CompanyID EmployeeName EmployeeName
12 NULL someone 2
12 someone 3 NULL
12 someone 4 someone 4
答案 0 :(得分:2)
试试这个:
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)
OP提供测试数据和预期结果集后编辑
试试这个(来自问题的表和测试数据):
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
输出:
CompanyID EmployeeName EmployeeName
----------- ------------------------------ ------------------------------
12 NULL someone 2
12 someone 3 NULL
12 someone 4 someone 4
(3 row(s) affected)
答案 1 :(得分:1)
试试这个
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
答案 2 :(得分:1)
FULL OUTER JOIN只能在companyID和employeeName上的TableA和TableB之间进行,因为如果它只存在于一个表中,那么这个值就是你想要填充的值。 获得此信息后,您可以与公司进行内部联接以从公司获取其他数据。
FULL OUTER JOIN解决方案:
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
我个人觉得很难用FULL OUTER JOINS来思考。我对此的处理方法是:通过在受影响的表之间创建UNION,然后使用左连接从两个表中获取数据,从而在需要时获取NULL,在结果中找到所需的独特EmployeeNames。
LEFT JOIN示例:
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
答案 3 :(得分:0)
以下是Dimitris Baltas答案的变体,它更接近我的想法。
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
我正在寻找的关键事项(这个示例不会这样做,但Dimitris'可能)是对CompanyID进行预过滤,以便执行计划不会筛选每个连接表的所有行在过滤出CompanyID之前。就我而言,两个连接的表格非常慢。
我认为我最终要做的就是继续使用sprocs。