Альтернативы self FULL OUTER JOIN для получения соответствия между двумя записями - PullRequest
4 голосов
/ 16 февраля 2012

в моей модели БД у меня есть две сущности: Entitlement и Entitlement_Data. Каждое Право идентифицируется с помощью инкрементного идентификатора (IDENTITY) и может иметь несколько записей Entitlement_Data, каждая из которых имеет свой Тип - который может быть 0 (Еженедельно) или 1 (Ежемесячно) (EntitlementID и Тип - PK для Entitlement_Data, EntitlementID - FK к таблице прав). Для каждого права мне нужно:

  1. Получить первое значение, отличное от NULL, из Monthly (Type = 1) или Weekly (Type = 0) Entitlement_Data для заданного набора атрибутов Entitlement_Data (SharesPaid, LocalTaxRate и т. Д.) - первой части ВЫБРАТЬ;
  2. Получите некоторые сведения о совпадении / несовпадении между записями Entitylement_Data за месяц и неделю (SharesPaid_Match и т. Д.) - последняя часть SELECT.

Это запрос, который я использую atm:

SELECT 
    COALESCE(MD.EntitlementID, WD.EntitlementID) AS EntitlementID,
    COALESCE(MD.LocalTaxRate, WD.LocalTaxRate) AS LocalTaxRate,
    COALESCE(MD.SharesPaid, WD.SharesPaid) AS SharesPaid,
    COALESCE(MD.LocalTaxAmount, WD.LocalTaxAmount) AS LocalTaxAmount,
    COALESCE(MD.LocalTaxEquivalent, WD.LocalTaxEquivalent) AS LocalTaxEquivalent,
    COALESCE(MD.NetReceived, WD.NetReceived) AS NetReceived,
    COALESCE(MD.LocalTaxCurrency, WD.LocalTaxCurrency) AS LocalTaxCurrency,
    COALESCE(MD.Currency, WD.Currency) AS Currency,
    COALESCE(MD.ReleaseDate, WD.ReleaseDate) AS ReleaseDate,
    (
        CASE
            WHEN MD.LocalTaxEquivalent IS NULL OR WD.LocalTaxEquivalent IS NULL THEN NULL
            WHEN MD.LocalTaxEquivalent <> WD.LocalTaxEquivalent THEN 0
            ELSE 1
        END
    ) AS LocalTaxEquivalent_Match,
    (
        CASE
            WHEN MD.NetReceived IS NULL OR WD.NetReceived IS NULL THEN NULL
            WHEN MD.NetReceived <> WD.NetReceived THEN 0
            ELSE 1
        END
    ) AS NetReceived_Match,
    (
        CASE
            WHEN MD.SharesPaid IS NULL OR WD.SharesPaid IS NULL THEN NULL
            WHEN MD.SharesPaid <> WD.SharesPaid THEN 0
            ELSE 1
        END
    ) AS SharesPaid_Match,
    (
        CASE
            WHEN MD.Currency IS NULL OR WD.Currency IS NULL THEN NULL
            WHEN MD.Currency <> WD.Currency THEN 0
            ELSE 1
        END
    ) AS Currency_Match,
    (
        CASE
            WHEN MD.DividendRate IS NULL OR WD.DividendRate IS NULL THEN NULL
            WHEN MD.DividendRate <> WD.DividendRate THEN 0
            ELSE 1
        END
    ) AS DividendRate_Match,
    (
        CASE
            WHEN MD.LocalTaxRate IS NULL OR WD.LocalTaxRate IS NULL THEN NULL
            WHEN MD.LocalTaxRate <> WD.LocalTaxRate THEN 0
            ELSE 1
        END
    ) AS LocalTaxRate_Match
FROM 
    Entitlement_Data MD
    FULL OUTER JOIN Entitlement_Data WD
        ON MD.EntitlementID = WD.EntitlementID
WHERE
    WD.Type = 0 AND MD.Type = 1

Есть ли способ избежать FULL OUTER JOIN и получить необходимую мне информацию? Я оценил использование GROUP BY, но, похоже, я не получил нужные результаты. Спасибо.

1 Ответ

4 голосов
/ 16 февраля 2012

Почему бы вам не left join перейти к "главной таблице", которая Entitlement, как в следующем коде:

select
    COALESCE(MD.EntitlementID, WD.EntitlementID) AS EntitlementID,
    COALESCE(MD.LocalTaxRate, WD.LocalTaxRate) AS LocalTaxRate,
    COALESCE(MD.SharesPaid, WD.SharesPaid) AS SharesPaid,
    COALESCE(MD.LocalTaxAmount, WD.LocalTaxAmount) AS LocalTaxAmount,
    COALESCE(MD.LocalTaxEquivalent, WD.LocalTaxEquivalent) AS LocalTaxEquivalent,
    COALESCE(MD.NetReceived, WD.NetReceived) AS NetReceived,
    COALESCE(MD.LocalTaxCurrency, WD.LocalTaxCurrency) AS LocalTaxCurrency,
    COALESCE(MD.Currency, WD.Currency) AS Currency,
    COALESCE(MD.ReleaseDate, WD.ReleaseDate) AS ReleaseDate,
    (
        CASE
            WHEN MD.LocalTaxEquivalent IS NULL OR WD.LocalTaxEquivalent IS NULL THEN NULL
            WHEN MD.LocalTaxEquivalent <> WD.LocalTaxEquivalent THEN 0
            ELSE 1
        END
    ) AS LocalTaxEquivalent_Match,
    (
        CASE
            WHEN MD.NetReceived IS NULL OR WD.NetReceived IS NULL THEN NULL
            WHEN MD.NetReceived <> WD.NetReceived THEN 0
            ELSE 1
        END
    ) AS NetReceived_Match,
    (
        CASE
            WHEN MD.SharesPaid IS NULL OR WD.SharesPaid IS NULL THEN NULL
            WHEN MD.SharesPaid <> WD.SharesPaid THEN 0
            ELSE 1
        END
    ) AS SharesPaid_Match,
    (
        CASE
            WHEN MD.Currency IS NULL OR WD.Currency IS NULL THEN NULL
            WHEN MD.Currency <> WD.Currency THEN 0
            ELSE 1
        END
    ) AS Currency_Match,
    (
        CASE
            WHEN MD.DividendRate IS NULL OR WD.DividendRate IS NULL THEN NULL
            WHEN MD.DividendRate <> WD.DividendRate THEN 0
            ELSE 1
        END
    ) AS DividendRate_Match,
    (
        CASE
            WHEN MD.LocalTaxRate IS NULL OR WD.LocalTaxRate IS NULL THEN NULL
            WHEN MD.LocalTaxRate <> WD.LocalTaxRate THEN 0
            ELSE 1
        END
    ) AS LocalTaxRate_Match
from Entitlement e
left join Entitlement_Data wd on e.id = wd.entitlementID and wd.type = 0
left join Entitlement_Data md on e.id = md.entitlementID and md.type = 1

Вы можете ограничить строки в Entitlement, которые имеют хотя бы одну строкув таблице Entitlement_Data (без учета слабо или ежемесячно), используя:

where wd.type is not null or md.type is not null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...