RIGHT JOIN 没有按预期工作

Ste*_*old 0 sql-server-2008 join sql-server

我有一个关于连接两个表的问题。

架构

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)
)
Run Code Online (Sandbox Code Playgroud)

[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;
Run Code Online (Sandbox Code Playgroud)

我对[StringData]存在表中匹配数据的搜索日期范围的期望是:

ID   | TimeStamp
6658 | 22.02.2016 10:00:00
6658 | 22.02.2016 11:00:00
6658 | 22.02.2016 12:00:00
Run Code Online (Sandbox Code Playgroud)

...并且在[StringData]表中不存在匹配数据的搜索日期范围内是这样的:

ID   | TimeStamp
6658 | NULL
Run Code Online (Sandbox Code Playgroud)

我在[StringData]表中不存在匹配数据的搜索日期范围内得到的是 0 行结果。为什么?

我只是想总是得到所有[DCString].[ID]的。我的 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;
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 6

如果我没有理解你的要求,你想在每一行DCString,即使存在不匹配的行StringData。您现在的两个查询不正确:

  1. 第一个执行DCString RIGHT JOIN StringData- 这与您似乎想要的相反(并且是大多数理智的人RIGHT JOIN尽可能避免的原因之一)。
  2. 第二个查询执行StringData LEFT JOIN DCString- 这落后于您似乎想要的。我建议将 the 更改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;
Run Code Online (Sandbox Code Playgroud)

进一步阅读: