У меня небольшая проблема, которую я не знаю, как ее решить - я никогда с ней не сталкивался. Я использую MS SQL и имею запрос SQL JOIN, который запрашивает две таблицы - страхование и кредиторы. Таблица страхования содержит всю информацию о полисе, а таблица Creditor содержит информацию о компании (название страховой компании / брокера и т. Д.).

Таблица страхования содержит два внешних ключа с именами CreditorID и BrokerID. Оба этих внешних ключа относятся к одному и тому же полю, являющемуся полем CreditorID в таблице Creditor (поскольку некоторые кредиторы являются одновременно страховыми компаниями И страховыми брокерами). Я не уверен в том, как написать запрос.

Например. Таблица страхования может выглядеть примерно так:

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

А таблица Creditor может выглядеть примерно так:

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

Итак, проблема в том, что когда я извлекаю информацию для определенного свойства, мне нужно дважды получить информацию из таблицы Creditor - один раз с помощью Insurance.CreditorID = Creditor.CreditorID и еще раз с помощью Insurance.CreditorID = Creditor.BrokerID.

Но я не знаю, как это сделать в одном соединении. Я пробовал это, но это не сработало (я получаю сообщение об ошибке "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. Хотя он работает, я не уверен, почему)

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'
0
Benny O'Neill 29 Апр 2014 в 12:28

5 ответов

Лучший ответ

Вам просто нужно использовать псевдоним таблицы в списке выражений 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 JOINs. Это потому, что вы показали, что ссылочные значения могут иметь значение NULL. Если вы не используете ВНЕШНИЕ СОЕДИНЕНИЯ, вы потеряете строки из таблицы страхования, что, на мой взгляд, для вас нежелательно.

0
Kevin Hogg 29 Апр 2014 в 09:01

Я думаю, что ты хочешь что-то вроде этого

 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, чтобы продемонстрировать (за вычетом столбцов в операторе select, которые не не существует в примерах таблиц). Здесь используется ваш исходный запрос, но ниже показан другой пример с LEFT OUTER JOIN.

РЕДАКТИРОВАТЬ:

Как указано ниже, LEFT JOIN было бы полезно, чтобы вы не отфильтровывали строки, где BrokerID равно NULL. Обновлен пример на SQLFiddle, чтобы показать это тоже.

0
Kevin Hogg 29 Апр 2014 в 08:57

Возможно, поможет левое соединение? Поскольку у вас может не быть идентификатора брокера во всех случаях.

 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'
0
Kevin Hogg 29 Апр 2014 в 09:00
 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'

Поскольку вы ссылаетесь на таблицу с использованием псевдонима (cred и cred1), вы должны использовать псевдоним в списке столбцов

0
Kevin Hogg 29 Апр 2014 в 09:01

В исходном запросе вы ссылаетесь на «Creditor.sCreditorName», однако вы используете псевдоним cred в объединении.

Кроме того, вы используете внутренние объединения, которые могут привести к появлению некоторых записей, если 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
0
Kevin Hogg 29 Апр 2014 в 09:18