【问题标题】:SQL join conditional either or not both?SQL 连接条件之一或不两者?
【发布时间】:2017-05-15 13:51:33
【问题描述】:

我有 3 个要加入的表和 2 个在其中一个联接中使用的变量。

我要做的是根据其中一个语句而不是两个语句来弄清楚如何加入。

这是当前查询:

SELECT DISTINCT
WR.Id,
CAL.Id as 'CalendarId',
T.[First Of Month],
T.[Last of Month],
WR.Supervisor,
WR.cd_Manager as [Manager], --Added to search by the Manager--
WR.[Shift] as 'ShiftId'
INTO #Workers
FROM #T T

--Calendar
RIGHT JOIN [dbo].[Calendar] CAL
ON  CAL.StartDate <= T.[Last of Month]
AND CAL.EndDate >= T.[First of Month]

--Workers
--This is the problem join
RIGHT JOIN [dbo].[Worker_Filtered]WR
ON WR.Supervisor  IN (SELECT Id FROM [dbo].[User] WHERE FullName IN(@Supervisors))
or (WR.Supervisor  IN (SELECT Id FROM [dbo].[User] WHERE FullName IN(@Supervisors))
    AND WR.cd_Manager IN(SELECT Id FROM [dbo].[User] WHERE FullNameIN(@Manager)))   --Added to search by the Manager--
AND WR.[Type] = '333E7907-EB80-4021-8CDB-5380F0EC89FF' --internal

WHERE CAL.Id = WR.Calendar
AND WR.[Shift] IS NOT NULL

我想要做的要么是基于Worker_Filtered 表匹配@Supervisor 的结果,要么(但不是两者)让它同时匹配@Supervisor@Manager

如果它匹配任何一个条件,它将被返回。这应该将返回的结果限制为同时具有 Supervisor 和 Manager 的 Worker,这将是一个比仅与 Supervisor 匹配的数据集更小的数据集。

更新

我上面的查询是为主管的工作人员提取数据的更大整体的一部分。

我还想将其限制为特定主管下属的经理。

例如,如果 @Supervisor = John Doe@Manager = Jane DoeJohn 有 9 个工人,其中 8 个在 Jane 的管理下,那么我希望最终结果显示每个月只有 8 个工人.使用当前查询,它仍然显示每个月的所有 9。

如果我将RIGHT JOIN 的一部分更改为:

WR.Supervisor  IN (SELECT Id FROM [dbo].[User] WHERE FullName IN (@Supervisors)) 
    AND WR.cd_Manager IN(SELECT Id FROM [dbo].[User] WHERE FullName IN(@Manager))

然后它只返回 12 行 NULL

更新 2

抱歉,这需要很长时间才能获得样本。我无法让 SQL Fiddle 为 SQL Server 2008/2014 工作,所以我改用 rextester:

Sample

这将结果显示为 108 行。但我想展示的只是前 96 行。

更新 3

我对@9​​87654322@ 做了一点更新。这确实得到了我想要的结果。我可以将@Manager 设置为NULL,它会提取所有108 条记录,或者我可以在其中拥有正确的经理名称,它只会提取与主管和经理都匹配的那些。

但是,我使用 IF ELSE 执行此操作,我希望避免这样做,因为它会重复插入到 Worker 表中的代码。

【问题讨论】:

  • 简化您的问题并生成一个小数据集可能会很有用,该数据集可以显示问题以及在具有不同变量值的数据集下给出您想要的输出。
  • 试着调整这部分代码RIGHT JOIN [dbo].[Worker_Filtered]WR ON WR.Supervisor IN (SELECT Id FROM [dbo].[User] WHERE FullName IN (@Supervisors) AND FullName NOT IN (@Manager))
  • @Joby 我试过调整它。我试过没有OR 我试过删除() 并且只拥有OR/AND FullName NOT IN(@Manager) 到目前为止没有任何效果。
  • @Tanner 这只是整个查询的一部分。最终结果显示了一年中每个月主管的工人数量。然后工作时间和一堆其他数据。这部分查询仅提取uniqueidentifier 类型的数据,然后用于获取其余数字。最终结果应该有 12 行,每个月 1 行。我将尝试在那里获取一些有意义的示例数据。
  • 我认为在WHERE 子句中包含CAL.Id = WR.Calendar 可以有效地将您的RIGHT JOIN 变成INNER JOIN。这可能是您问题的根源吗?是的,具有预期输出的样本数据会非常有帮助。

标签: sql-server sql-server-2008 join


【解决方案1】:

更新 3 中对预期结果的描述现在一切都清楚了,谢谢。您的“问题”加入需要:

RIGHT JOIN Worker_Filtered wr on (wr.Supervisor in(@Supervisors) 
    and case when @Manager is null then 1
             else case when wr.Manager in(@Manager) then 1 else 0 end
             end = 1)

顺便说一句,我不知道您希望 in(@Supervisors) 实现什么,但如果您希望提供一个逗号分隔的主管列表作为单个字符串并让 wr.Supervisor 匹配任何一个他们然后你会失望的。如果您使用的是 = @Supervisors,则此查询的工作方式完全相同。

【讨论】:

  • 就是这样!有用!奇怪的是,in(@Supervisors) 当它是一个逗号分隔的列表时也能正常工作。我从来没有遇到过问题。
  • 很高兴有帮助。 in(@Supervisors) 对我不起作用,但如果它对你有用,那就是奖励!
  • 我使用的是 SQL Server 2014,不知道对你有没有影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-05
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
相关资源
最近更新 更多