SQL Join Query - 两个FK,一个字段

时间:2014-04-29 08:28:14

标签: sql sql-server join

我有一个小问题,我不确定如何解决 - 我以前从未遇到过。我使用的是MS SQL,并且有一个查询两个表的SQL JOIN查询 - 保险和债权人。保险表包含所有保单细节,而债权人表保存公司详情(保险公司/经纪人姓名等)。

Insurance表包含两个名为CreditorID和BrokerID的外键。这两个外键都与相同的字段相关,即债权人表中的CreditorID字段(因为一些债权人既是保险公司又是保险经纪人)。我不确定如何编写查询。

E.g。保险表可能如下所示:

lInsuranceID   lCreditorID  lBrokerID  mLastPremium  dDatePaid  sPolicyNumber
1              1            null       1000.00       28/03/2014 12345
2              14           1          2000.00       17/03/2014 67891

债权人表可能如下所示:

lCreditorID   sCreditorName
1             Frank's Insurance COMPANY
14            Frank's Insurance BROKER

所以问题是,当我检索特定属性的信息时,我需要从Creditor表中提取两次信息 - 一次使用Insurance.CreditorID = Creditor.CreditorID,再次使用Insurance.CreditorID = Creditor.BrokerID。 / p>

但我不知道如何在一次加入中做到这一点。我试过这个,但它没有用(我得到的错误是" Creditor.sCreditorName"无法绑定:

 SELECT Insurance.sPolicyNumber,
        Insurance.dDatePaid,
        Insurance.dRenewal,
        Insurance.mLastPremium,
        Creditor.sCreditorName
   FROM Insurance
        INNER JOIN Creditor cred ON Insurance.lCreditorID = cred.lCreditorID
        INNER JOIN Creditor cred1 ON Insurance.lBrokerID = cred1.lCreditorID
  WHERE Insurance.lOwnersCorporationID = '1'

有什么建议吗?

修改 好的,谢谢所有的提示,窥视。我将查询修改为看起来像这样,它似乎正在工作(我就是这样一个JOIN noob。即使它有效,我也不确定为什么)

SELECT Insurance.sPolicyNumber, Insurance.dDatePaid, Insurance.dRenewal, Insurance.mLastPremium, cred.sCreditorName as Company, cred1.sCreditorName as Broker
FROM Insurance
LEFT JOIN Creditor cred ON Insurance.lCreditorID = cred.lCreditorID
LEFT JOIN Creditor cred1 ON Insurance.lBrokerID = cred1.lCreditorID
WHERE Insurance.lOwnersCorporationID = '1'

5 个答案:

答案 0 :(得分:0)

我认为你想要的是这样的

 SELECT Insurance.sPolicyNumber,
        Insurance.dDatePaid,
        Insurance.dRenewal,
        Insurance.mLastPremium,
        cred.sCreditorName AS Creditor,
        cred1.sCreditorName AS Broker
   FROM Insurance
        INNER JOIN Creditor cred ON Insurance.lCreditorID = cred.lCreditorID
        INNER JOIN Creditor cred1 ON Insurance.lBrokerID = cred1.lCreditorID
  WHERE Insurance.lOwnersCorporationID = '1'

我添加了SQLFiddle example来演示(减去select语句中不存在于示例表中的列)。这会使用您的原始查询,但请参阅下面的另一个LEFT OUTER JOIN示例。

修改

如下所述,LEFT JOIN会很有用,因此您不会过滤BrokerIDNULL的行。更新了SQLFiddle上的示例以显示此内容。

答案 1 :(得分:0)

也许左连接可能有帮助?由于您可能在所有实例中都没有Broker ID。

 SELECT Insurance.sPolicyNumber,
        Insurance.dDatePaid,
        Insurance.dRenewal,
        Insurance.mLastPremium,
        Creditor.sCreditorName
   FROM Insurance
        INNER JOIN Creditor cred ON Insurance.lCreditorID = cred.lCreditorID
         LEFT JOIN Creditor cred1 ON Insurance.lBrokerID = cred1.lCreditorID
  WHERE Insurance.lOwnersCorporationID = '1'

答案 2 :(得分:0)

您只需要在SELECT表达式列表中使用表别名:

 SELECT i.sPolicyNumber,
        i.dDatePaid,
        i.dRenewal,
        i.mLastPremium,
        c.sCreditorName,
        b.sCreditorName
   FROM Insurance i
        LEFT JOIN Creditor  c ON c.lCreditorID = i.lCreditorID
        LEFT JOIN Creditor  b ON b.lCreditorID = i.lBrokerID
  WHERE Insurance.lOwnersCorporationID = '1'

请注意,我切换到LEFT OUTER JOIN。这是因为您已经证明引用值可能是NULLable。如果您不使用OUTER JOIN,您将从Insurance表中删除行,我认为这对您不利。

答案 3 :(得分:0)

 SELECT Insurance.sPolicyNumber,
        Insurance.dDatePaid,
        Insurance.dRenewal, 
        Insurance.mLastPremium, 
        -- the changed columns
        cred.sCreditorName AS CREDITOR,
        cred1.sCreditorName AS BROKER,  
   FROM Insurance
        INNER JOIN Creditor cred ON Insurance.lCreditorID = cred.lCreditorID
        LEFT OUTER JOIN Creditor cred1 ON Insurance.lBrokerID = cred1.lCreditorID
  WHERE Insurance.lOwnersCorporationID = '1'

当您使用Alias(cred和cred1)引用该表时,您必须在列列表中使用别名

答案 4 :(得分:0)

在原始查询中,您将引用“Creditor.sCreditorName”,但是您在联接中使用了别名。

另外,如果FK为空,则使用内部联接,这可能会导致一些条目。例如,您的lInsuranceID = 1的条目将被遗漏。

正确的查询可能是

 SELECT ins.sPolicyNumber,
        ins.dDatePaid,
        ins.dRenewal,
        ins.mLastPremium,
        cred.sCreditorName as CreditorName,
        brok.sCreditorName as BrokerName
   FROM Insurance ins
        LEFT JOIN Creditor cred ON ins.lCreditorID = cred.lCreditorID
        LEFT JOIN Creditor brok ON ins.lBrokerID = brok.lCreditorID
  WHERE ins.lOwnersCorporationID = '1'

MSSQL中的一些测试:

declare @Insurance table
(
    lInsuranceID int,
    lCreditorID  int,
    lBrokerID  int,
    mLastPremium  money,
    dDatePaid  date,
    sPolicyNumber int
)

 INSERT INTO @Insurance
        (lInsuranceID, lCreditorID, lBrokerID, mLastPremium, dDatePaid,
         sPolicyNumber)
 SELECT 1, 1, null, 1000.00, '2014-03-28', 12345
  UNION ALL
 SELECT 2, 14, 1, 2000.00, '2014-03-17', 67891

declare @Creditor table
(
    lCreditorID int,
    sCreditorName varchar(64)
)

 INSERT INTO @Creditor
        (lCreditorID, sCreditorName)
 SELECT 1, 'Frank''s Insurance COMPANY'
  UNION ALL
 SELECT 14, 'Frank''s Insurance BROKER'


 SELECT ins.sPolicyNumber,
        ins.dDatePaid,
        ins.mLastPremium,
        brok.sCreditorName as BrokerName,
        cred.sCreditorName as CreditorName
   FROM @Insurance ins
        LEFT JOIN @Creditor cred on cred.lCreditorID = ins.lCreditorID
        LEFT JOIN @Creditor brok on brok.lCreditorID = ins.lBrokerID