我正在构建一个来自多个表的查询,并遇到了我不完全理解的JOIN语句的实现......
作为一个例子,我有这些表:
Applications AS a - columns(ID, MemberName)
ContractAHistory AS ca - columns(ID, AppID, PolicyNumber)
ContractBHistory AS cb - columns(ID, AppID, PolicyNumber)
MemberPolicy AS m - columns(ID, PolicyNumber)
为清楚起见,有两种不同的合同(A和B),每种合同都分配了一个PolicyNumber。
我希望能够像这样进行查询:
SELECT * FROM Applications a
FULL OUTER JOIN ContractAHistory ca ON a.ID=ca.AppID
FULL OUTER JOIN ContractBHistory cb ON a.ID=cb.AppID
FULL OUTER JOIN MemberPolicy m ON
(ca.PolicyNumber=m.PolicyNumber AND cb.PolicyNumber=m.PolicyNumber)
WHERE m.PolicyNumber = 79301;
然而,这对我没有用,所以我已经解决了这个问题:
SELECT * FROM Applications a
FULL OUTER JOIN ContractAHistory ca ON a.ID=ca.AppID
FULL OUTER JOIN ContractBHistory cb ON a.ID=cb.AppID
FULL OUTER JOIN MemberPolicy m1 ON ca.PolicyNumber=m1.PolicyNumber
FULL OUTER JOIN MemberPolicy m2 ON ca.PolicyNumber=m2.PolicyNumber
WHERE m1.PolicyNumber = 79301 OR m2.PolicyNumber = 79301;
不幸的是,这意味着我的WHERE子句需要更详细:
... WHERE m1.PolicyNumber = 79301 OR m2.PolicyNumber = 79301;
而不是
... WHERE m.PolicyNumber = 79301;
在这种情况下是否有可能实现我的理想?最后,我希望能够在正确构造的SQL查询中使用所有这些干净的WHERE子句:
... WHERE a.MemberName = 'Annika Hansen';
... WHERE m.PolicyNumber = 79301;
... WHERE m.ID = 79;
... WHERE a.ID = 74656;
我正在使用SQL-Server,但我试图将此作为关于SQL的一般问题。如果我不清楚,请告诉我 - 提前谢谢你!
以下是一个不良结果的示例(感谢@TheEsisia对于大部分内容:)
declare @Applications table (ID int, MemberName varchar(30))
declare @ContractAHistory table (ID int, AppID int, PolicyNumber varchar(30))
declare @ContractBHistory table (ID int, AppID int, PolicyNumber varchar(30))
declare @MemberPolicy table (ID int, PolicyNumber varchar(30))
Insert Into @Applications Values
(1, 'AA')
,(2, 'BB')
,(3, 'CC')
,(4, 'DD')
Insert Into @ContractAHistory Values
(1, 1, 'A')
,(2, 2, 'B')
Insert Into @ContractBHistory Values
(1, 3, 'H12007')
,(2, 4, 'GT31')
Insert Into @MemberPolicy Values
(1, 'A')
,(2, 'B')
,(3, 'H12007')
,(4, 'GT31')
SELECT * FROM @Applications a
FULL OUTER JOIN @ContractAHistory ca ON a.ID=ca.AppID
FULL OUTER JOIN @ContractBHistory cb ON a.ID=cb.AppID
FULL OUTER JOIN @MemberPolicy m ON
(ca.PolicyNumber=m.PolicyNumber AND cb.PolicyNumber=m.PolicyNumber)
WHERE m.PolicyNumber = 'GT31';
更新: @TheEsisia帮助我看到在最后一个查询中用OR替换AND可以达到我想要的效果。但回答@ ThorstenKettner的问题:我当然可能不需要所有的FULL OUTER JOIN - 但是,我确实希望根据特定的WHERE子句提取所有信息。我只能通过一个拼图获得信息请求,所以我想基于m.ID或AppID或PolicyNumber提取所有内容。为了提高效率,我希望使用相同的主查询,并且只适当地更改WHERE子句。此外,每个PolicyNumber匹配一个成员和一个合同(A或B)和一个a.ID.这就是复杂性的来源:我从来没有从PolicyNumber知道它是哪种合同。我希望这有助于澄清我的用例。谢谢大家。
答案 0 :(得分:2)
我不知道你为什么说“这对我不起作用”,因为它对我有用:
declare @Applications table (ID int, MemberName varchar(30))
declare @ContractAHistory table (ID int, AppID int, PolicyNumber varchar(30))
declare @ContractBHistory table (ID int, AppID int, PolicyNumber varchar(30))
declare @MemberPolicy table (ID int, PolicyNumber varchar(30))
Insert Into @Applications Values
(1, 'AA')
,(2, 'BB')
,(3, 'CC')
,(4, 'DD')
Insert Into @ContractAHistory Values
(1, 1, 'A')
,(2, 2, 'B')
Insert Into @ContractBHistory Values
(1, 2, 'H12007')
,(2, 3, 'GT31')
Insert Into @MemberPolicy Values
(1, 'WW2007')
,(2, 'LL2009')
,(3, 'JJ2010')
,(4, 'RR2009')
SELECT * FROM @Applications a
FULL OUTER JOIN @ContractAHistory ca ON a.ID=ca.AppID
FULL OUTER JOIN @ContractBHistory cb ON a.ID=cb.AppID
FULL OUTER JOIN @MemberPolicy m ON
(ca.PolicyNumber=m.PolicyNumber AND cb.PolicyNumber=m.PolicyNumber)
<强>更新强>
如果您的原始问题与此问题完全相同,那么您既不需要AND
也不需要OR
。您不需要具有该条件的左侧:
declare @Applications table (ID int, MemberName varchar(30))
declare @ContractAHistory table (ID int, AppID int, PolicyNumber varchar(30))
declare @ContractBHistory table (ID int, AppID int, PolicyNumber varchar(30))
declare @MemberPolicy table (ID int, PolicyNumber varchar(30))
Insert Into @Applications Values
(1, 'AA')
,(2, 'BB')
,(3, 'CC')
,(4, 'DD')
Insert Into @ContractAHistory Values
(1, 1, 'A')
,(2, 2, 'B')
Insert Into @ContractBHistory Values
(1, 3, 'H12007')
,(2, 4, 'GT31')
Insert Into @MemberPolicy Values
(1, 'A')
,(2, 'B')
,(3, 'H12007')
,(4, 'GT31')
SELECT * FROM @Applications a
FULL OUTER JOIN @ContractAHistory ca ON a.ID=ca.AppID
FULL OUTER JOIN @ContractBHistory cb ON a.ID=cb.AppID
FULL OUTER JOIN @MemberPolicy m ON
cb.PolicyNumber=m.PolicyNumber
WHERE m.PolicyNumber = 'GT31';
注意:您的原始查询可能仍需要OR
,但除非我们知道您要实现的目标,否则没有人可以告诉您。
点击此链接以使用查询:link
答案 1 :(得分:1)
实际上,它非常简单。创建两个相同的表A和B.
CREATE TABLE A (ID INT NULL, NAME VARCHAR(5) NULL)
CREATE TABLE B (ID INT NULL, NAME VARCHAR(5) NULL)
--TABLE A
INSERT A
SELECT 1, 'John'
UNION ALL
SELECT 2, 'Henry'
--TABLE B
INSERT B
SELECT 1, 'John'
UNION ALL
SELECT 2, 'Henry'
--scenario #1:
SELECT *
FROM A
LEFT JOIN B
ON A.ID = B.ID AND B.NAME = 'Henry'
--scenario #2:
SELECT *
FROM A
LEFT JOIN B
ON A.ID = B.ID
WHERE B.NAME = 'Henry'
根据方案#1,条件A.ID = B.ID
和B.NAME = 'Henry'
将首先在执行左连接之前过滤表A和B.
根据方案#2,条件A.ID = B.ID
将在加入之前执行过滤,而条件B.NAME = 'Henry'
将在执行左连接后过滤完整数据集。
答案 2 :(得分:1)
以下是我们应该如何访问表格:
完整的查询:
SELECT *
FROM @MemberPolicy m
LEFT OUTER JOIN @ContractAHistory ca ON ca.PolicyNumber = m.PolicyNumber
LEFT OUTER JOIN @ContractBHistory cb ON cb.PolicyNumber = m.PolicyNumber
INNER JOIN @Applications a ON a.ID IN (ca.AppID, cb.AppID)
WHERE m.PolicyNumber = 'GT31';
如果合同非常相似,您也可以合并两个表。 (但在这种情况下,更改数据库设计可能会好得多,并且只为两个合同类型开始使用这一个表。)在这种情况下,我们不需要任何外部联接;我们选择政策,合同及其申请:
SELECT *
FROM @MemberPolicy m
INNER JOIN
(
SELECT PolicyNumber, title, description, client, a_only_col, null as b_only_col
FROM @ContractAHistory
UNION ALL
SELECT PolicyNumber, title, description, client, null as a_only_col, b_only_col
FROM @ContractBHistory
) c ON c.PolicyNumber = m.PolicyNumber
INNER JOIN @Applications a ON a.ID = c.AppID
WHERE m.PolicyNumber = 'GT31';