Sql-Server

RIGHT JOIN 沒有按預期工作

  • May 7, 2020

我有一個關於加入兩個表的問題。

架構

CREATE TABLE [dbo].[DCString] (
   [ID] [bigint] IDENTITY(1,1) NOT NULL,
   [DCDistributionBoxID] [bigint] NOT NULL,
   [CurrentMPP] [decimal](18, 2) NULL,
   CONSTRAINT [PrimaryKey3] PRIMARY KEY CLUSTERED ( [ID] ASC )
)

ALTER TABLE [dbo].[DCString]
   ADD CONSTRAINT [FK_DCString_DCDistributionBox] FOREIGN KEY([DCDistributionBoxID])
   REFERENCES [dbo].[DCDistributionBox] ([ID])

CREATE TABLE [dbo].[StringData](
   [DCStringID] [bigint] NOT NULL,
   [TimeStamp] [datetime] NOT NULL,
   [DCCurrent] [decimal](18, 2) NULL,
   CONSTRAINT [PrimaryKey4] PRIMARY KEY CLUSTERED ( [TimeStamp] DESC, [DCStringID] ASC)
)

[StringData]表具有以下儲存統計資訊:

  • 數據空間:26,901.86 MB
  • 行數:131,827,749
  • 分區:真
  • 分區數:62

用法

我現在想將[StringData]表中的數據與表中的數據連接起來[DCString]

就像是:

declare @begin datetime = '22.02.2016';
declare @end datetime = '23.02.2016';
declare @dcStringID bigint = 6658;

SELECT [DCString].[ID], [StringData].[TimeStamp]
FROM [StringData]
RIGHT OUTER JOIN [StringData] ON [StringData].[DCStringID] = [DCString].[ID]
WHERE [StringData].[ID] = @dcStringID
AND [StringData].[TimeStamp] >= @begin
AND [StringData].[TimeStamp] < @end;

我對[StringData]錶中存在匹配數據的搜尋日期範圍的期望是:

ID   | TimeStamp
6658 | 22.02.2016 10:00:00
6658 | 22.02.2016 11:00:00
6658 | 22.02.2016 12:00:00

…並且在[StringData]表中不存在匹配數據的搜尋日期範圍內是這樣的:

ID   | TimeStamp
6658 | NULL

我在[StringData]表中不存在匹配數據的搜尋日期範圍內得到的是 0 行結果。為什麼?

我只是想總是得到所有[DCString].[ID]的s。我的 JOIN 有什麼問題還是我完全搞砸了?

更新 1(與@Aaron Bertrand 的回答有關):

我已經嘗試過你的方法,但我必須取消測試查詢,因為 10 分鐘後它仍在執行。它看起來像這樣:

declare @begin datetime = '22.02.2016';
declare @end datetime = '23.02.2016';
declare @dcStringID bigint = 6658;

SELECT [DCString].[ID], [StringData].[TimeStamp]    
FROM [StringData]    
LEFT JOIN [DCString] 
   ON [StringData].[DCStringID] = [DCString].[ID] 
   AND [StringData].[TimeStamp] >= @begin
   AND [StringData].[TimeStamp] < @end
WHERE [StringData].[ID] = @dcStringID;

如果我正確理解您的要求,您希望在 中的每一行DCString,即使 中沒有匹配的行StringData。您現在的兩個查詢不正確:

  1. 第一個執行DCString RIGHT JOIN StringData- 這與您似乎想要的相反(這是大多數理智的人RIGHT JOIN盡可能避免的原因之一)。
  2. 第二個查詢執行StringData LEFT JOIN DCString- 這落後於您似乎想要的。我建議將 更改RIGHT JOIN為 a LEFT JOIN,而不更改表格順序,但您也交換了表格,沒有淨變化。為什麼那個人目前沒有回來可能是由於很多事情,我們無法推測。試著制定一個估計的計劃,看看你是否會成為這些原因的犧牲品。

同樣,基於我認為你想要的(如果你提供一些樣本數據和期望的結果,你會得到更好的答案):

-- don't use regional, ambiguous formats like dd.mm.yyyy:
-- also you can declare multiple variables in one statement

DECLARE @begin datetime    = '20160222',
       @end   datetime    = '20160223',
       @dcStringID bigint = 6658;

-- don't litter your code with square brackets except where necessary:

SELECT d.ID, s.[TimeStamp] -- bad choice for a column name

-- always use schema prefix!
FROM dbo.DCString AS d
LEFT OUTER JOIN dbo.StringData AS s
 ON d.ID = s.DCStringID
 AND s.[TimeStamp] >= @begin
 AND s.[TimeStamp] <  @end
WHERE d.ID = @dcStringID;

進一步閱讀:

引用自:https://dba.stackexchange.com/questions/129747