【问题标题】:Conditional Inner Join条件内连接
【发布时间】:2011-11-08 06:38:08
【问题描述】:

我希望能够根据表达式的结果对两个表进行内部连接。

到目前为止我一直在尝试什么:

INNER JOIN CASE WHEN RegT.Type = 1 THEN TimeRegistration ELSE DrivingRegistration AS RReg
ON
RReg.RegistreringsId = R.Id

RegT 是我在此加入之前所做的加入:

INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id

此 SQL 脚本不起作用。

总而言之,如果Type 为1,那么它应该加入TimeRegistration 表,否则它应该加入DrivingRegistration

解决方案:

在我的选择语句中,我执行了以下连接:

INNER JOIN  RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
LEFT OUTER JOIN TimeRegistration AS TReg ON TReg.RegistreringsId = R.Id AND RegT.Type = 1
LEFT OUTER JOIN DrivingRegistration AS DReg ON DReg.RegistreringsId = R.Id AND RegT.Type <>1

然后我编辑了我的where-clause 以输出正确,具体取决于RegType,如下所示:

WHERE (CASE RegT.Type WHEN 1 THEN TReg.RegistreringsId ELSE DReg.RegistreringsId END = R.Id)

【问题讨论】:

  • 你不能那样做! CASE 不能用于动态交换查询的随机部分。这些表的结构是否相同?
  • 您是否收到错误消息?如果有,是什么?

标签: sql sql-server tsql join inner-join


【解决方案1】:

尝试使用 LEFT JOIN 将两个表都放入查询中

LEFT JOIN TimeRegistration TR ON r.rid = TR.Id AND RegT.type =1 
LEFT JOIN DrivingRegistration DR ON r.rid = DR.Id AND RegT.type <>1 

现在,在你的选择子句中,使用

CASE RegType.Type WHEN 1 THEN TR.SomeField ELSE DR.someField END as SomeField

另一种选择是使用动态 SQL

【讨论】:

  • 太棒了,Sparky 和 ​​David 的建议都有帮助!将我的问题编辑为我所做的工作。
【解决方案2】:

您可能需要执行两个左连接,一个到TimeRegistration,一个到DrivingRegistration,然后从相应的连接表中返回您想要的字段,如下所示:

LEFT JOIN TimeRegistration ON TimeRegistration.RegistreringsId = R.Id
LEFT JOIN DrivingRegistration ON DrivingRegistration.RegistreringsId = R.Id

而你的 select 语句会是这样的:

SELECT CASE WHEN RegT.Type = 1 THEN TimeRegistration.Foo ELSE DrivingRegistration.Bar END

我喜欢你正在尝试做的事情,但我不认为 SQL 有那么聪明。

【讨论】:

    【解决方案3】:
    SELECT
      R.foo, tr.bar
    FROM
      SomeTable AS R
      INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id 
                                              AND RegT1.Type = 1
      INNER JOIN TimeRegistration AS tr    ON /* whatever */
    
    UNION 
    
    SELECT
      R.foo, dr.bar
    FROM
      SomeTable AS R
      INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id 
                                              AND RegT1.Type = 2
      INNER JOIN DrivingRegistration AS dr ON /* whatever */
    

    【讨论】:

    • +1 虽然可能需要UNION ALL。如果这些表与 Union 兼容,则这些表可能位于带有 type 列的 CTE 中,以避免重复 JOIN 逻辑,但不确定执行计划会是什么样子。
    • @Martin:有了正确的索引,两个连接应该很快。我假设由于两个目标表不同,所以不需要 UNION ALL。
    【解决方案4】:

    所以我有一个场景,其中一个表中有三个电子邮件列(不要问为什么),它们中的任何一个都可能为空(或空)。在这个示例代码中,我将只处理它为 null 的情况。

    我必须通过任何电子邮件将其加入另一个表以检索用户的名字。

    这是有效的

    select  
    
    m.email1,
    m.email2,
    m.email3, 
    m2.firstName
    
    from MyTable m
    
    left join MyOtherTable m2 on m2.Email = 
    case when m.email1 is null then 
    
        case when m.email2 is null then 
    
            case when m.email3 null then 
                'nonexistent@mydomain.com' -- i stopped here
            else m.email3 end
    
        else wm.email2 end
    
    else m.email1 end
    

    显然你会包括更多的条件,比如

    case when m.email1 is null or m.email1 = '' then ...
    

    覆盖空值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-31
      • 1970-01-01
      • 1970-01-01
      • 2018-01-10
      • 2023-03-04
      • 2014-11-01
      • 1970-01-01
      相关资源
      最近更新 更多