2016-06-20 78 views
0

我有以下問題sql查詢我需要幫助,因爲我無法得到我的頭。多個標準或混亂的地方

我想要檢索我的預訂表的課程列表,唯一的是我需要確保課程仍然有效,因爲我有一個可以做兩件事的覆蓋表。

  1. 當一個班級去旅行時,我想重寫顯示的課程,所以我包含了一個開始日期和結束日期。如果課程落在這個範圍內,那麼我不想重新獲得課程。

2我的覆蓋表中有一個isNoMoreLesson布爾型字段。如果類已經完成,我要永久排除觸發這個先前預訂的教訓

SELECT DISTINCT LessonSubset.SubjectName, 
LessonSubset.Day, 
LessonSubset.StartTime, 
LessonSubset.EndTime, 
LessonSubset.fk_PeriodInformationID 

FROM LessonSubset 

LEFT JOIN OverrideLesson ON 
(LessonSubset.fk_ResourceID = OverrideLesson.fk_ResourceID AND 
LessonSubset.fk_PeriodInformationID = OverrideLesson.fk_PeriodInformationID) 

WHERE LessonSubset.fk_ResourceID = ‘XABCDE' AND LessonSubset.Day = ‘Mon' AND 
(OverrideLesson.isNoMoreLesson != 1 OR booking_date < OverrideLesson.EndDate AND 
booking_date< OverrideLesson.StartDate) 

ORDER BY LessonSubset.Day ASC 
+1

你能顯示一些樣本數據和預期的結果嗎? –

+0

這是否返回無效的結果或錯誤?我假設結果無效......如果是這樣,你會得到太多結果還是不夠? –

+0

我根本得不到結果。 – JK36

回答

1

如果你做了左連接,你不應該把一個WHERE子句左側連接表(或您將得到的結果相同內部連接)。

因此,無論你想要一個左連接(比將overrideLesson中的子句放在左連接子句中)還是進行內連接。

由於您僅從LessonSubset獲取數據,並希望根據OverrideLesson限制排除數據,因此我認爲您需要一個內部聯接。

然後,如果您沒有考慮優先順序(您應該放置括號),那麼您會混合使用「或」和「與」,這可能會帶來一些奇怪的結果。我想(但不是很清楚)你的AND/OR邏輯不是你想要的。

所以

SELECT DISTINCT 
    LessonSubset.SubjectName, 
    LessonSubset.Day, 
    LessonSubset.StartTime, 
    LessonSubset.EndTime, 
    LessonSubset.fk_PeriodInformationID 

FROM LessonSubset 

LEFT JOIN OverrideLesson ON 
    LessonSubset.fk_ResourceID = OverrideLesson.fk_ResourceID AND 
    LessonSubset.fk_PeriodInformationID = OverrideLesson.fk_PeriodInformationID AND 
    --include the restrictions in the left join, and change the "and/or logic" 
    OverrideLesson.isNoMoreLesson != 1 AND 
    --take only if booking_date is out of range 
    (booking_date > OverrideLesson.EndDate OR booking_date < OverrideLesson.StartDate) 

WHERE LessonSubset.fk_ResourceID = 'XABCDE' AND LessonSubset.Day = 'Mon' 

ORDER BY LessonSubset.Day ASC 

編輯: 如果你想排除一些成果,它可能是更清晰的使用NOT EXISTS子句

SELECT DISTINCT 
    ls.SubjectName, 
    ls.Day, 
    ls.StartTime, 
    ls.EndTime, 
    ls.fk_PeriodInformationID 

FROM LessonSubset ls 
WHERE ls.fk_ResourceID = 'XABCDE' AND ls.Day = 'Mon' 
AND NOT EXISTS (SELECT NULL 
       FROM OverrideLesson ol 
       WHERE 
       ls.fk_ResourceID = ol.fk_ResourceID AND 
       ls.fk_PeriodInformationID = ol.fk_PeriodInformationID AND 
       ol.isNoMoreLesson != 1 AND 
       (booking_date > ol.EndDate OR booking_date < ol.StartDate)) 

ORDER BY ls.Day ASC 
+0

最後一塊遺漏的是WHERE OverrideLesson.PrimaryKeyField爲null。 OP要求沒有顯示它們,所以這是我的假設,你想排除並刪除LessonSubset和OverrideLesson之間的匹配記錄 – Matt

+0

@Matt嗯,我在我的答案中寫道:在這種情況下,內部聯接就足夠了(或更好的是,使用NOT EXISTS子句而不是聯接) –

+0

否,因爲他想排除/刪除數據集中的匹配。所以我對問題的理解只記錄沒有被覆蓋的應該返回。在進行左連接時,如果不匹配,則右側表的主鍵在不匹配時將爲NULL。所以影響是你消除所有記錄之間的表匹配,它不會成爲一個內部連接 – Matt

0

下面是一個簡單的模式,將顯示你的想法如何使用LEFT JOIN來排除記錄與表之間的匹配情況。所有加入要求應在其他答案/評論提及的其他聯繫人的「ON」部分中。如果您沒有將它們放在該部分中,並且將它們留在where子句中,則必須考慮空值,否則將限制查詢並基本上將結果變爲與inner join相同。有一個例外是,如果某個字段不匹配(例如,第二個表的主鍵),那麼您將始終知道的字段將爲null,並將其條件等於NULL。這是爲了排除你不想要的記錄。如果你想要所有的東西,那就不要限制那個where子句。

CREATE TABLE dbo.T1 (
    Id INT IDENTITY(1,1) 
    ,C CHAR(1) 
) 

CREATE TABLE dbo.T2 (
    PKId INT 
) 

INSERT INTO dbo.T1 (C) 
VALUES ('A'),('B'),('C'),('D') 

INSERT INTO dbo.T2 (PKId) 
VALUES (1),(4) 

SELECT * 
FROM 
    dbo.T1 t1 
    LEFT JOIN dbo.T2 t2 
    ON t1.Id = t2.PKId 
WHERE 
    t2.PKId IS NULL