【问题标题】:Postgres SQL Case Join When not Stopping at First Case Match在第一个案例匹配时不停止的 Postgres SQL 案例连接
【发布时间】:2020-04-02 07:38:17
【问题描述】:

我正在尝试使用 Postgres SQL 进行案例连接,我希望在第一个匹配的案例之后停止搜索

select *

from 
table1 a

left join table2 b
on a.cond1 = b.cond1
    and case when a.cond2 = b.cond2 and a.cond3 = b.cond3
                 then 1
             when a.cond4 = b.cond4
                 then 1 
             else 0
        end = 1 

目的是如果 cond2 和 cond3 匹配就停止,只使用 table2 中匹配的行,否则尝试在 cond4 上匹配。但是,结果是保留满足这两个条件的行。我的 SQL 查询中有错误吗?

示例:

table1
id, cond1, cond2, cond3, cond4
1, 1, 1, 1, 1
2, 1, 0, 1, 1
3, 0, 1, 1, 0
4, 1, 1, 0, 0

table2
cond1, cond2, cond3, cond4, tag
1, 1, 1, 1, apple
1, 1, 0, 1, banana

结果

id, tag
1, apple
2, banana
3, null
4, null

但我要加入额外的 1、香蕉

【问题讨论】:

  • 请添加示例样本数据和预期输出。
  • ON 子句中使用AND/OR 构造而不是case 表达式通常会更好。
  • @jarlh 您能否详细说明在此示例中将如何完成?谢谢!
  • 您的查询正在执行您要求它执行的操作。您需要使用“join”(或inner join)而不是“left join”(“left outer join”的缩写)。
  • @belayer 我得到 1,apple 和 1,banana 结果,但我只想要 1,apple,不管它是内连接还是左连接

标签: sql postgresql join case


【解决方案1】:

你可以试试 CTE

with cte as(
select count(case when a.cond2 = b.cond2 and a.cond3 = b.cond3 then 1 else 0 end) 
checkcondition1, 
   count(case when a.cond4=b.cond4 then 1 else 0 end) checkcondition2 
from table1 a
join table2 b on a.cond1 = b.cond1
)
select a.id, b.tag
from table1 a
left join table2 b
 on a.cond1 = b.cond1
and case when (select count(*) from cte where checkcondition1>0)>0 and a.cond2 = 
b.cond2 and a.cond3 = b.cond3
             then 1
         when (select count(*) from cte where checkcondition1=0 and 
checkcondition1>0)>0 and a.cond4=b.cond4
             then 1
         else 0
    end = 1 

【讨论】:

  • 那将香蕉匹配到 4,而不是 2。我还在试图理解为什么香蕉不应该匹配 1。是因为 1 已经被苹果匹配了吗? IE。比赛应该是排他的?
  • @AndyN 是的,目的是如果第一个条件匹配,即 cond2 和 cond3,然后使用它,否则检查第二个条件,即 cond4
  • @AndyN,预期的结果是什么?上面的查询给出了问题中所问的结果
  • @user2392965,这回答了你的问题吗?
  • @KrishnaMohanVarma 我不认为 id4 应该匹配任何东西
【解决方案2】:

我想你想要一个lateral join。如果a中的每一行只有一个匹配行:

select *
from table1 a left join lateral
     (select b.*
      from table2 b
      where a.cond1 = b.cond1 and
            (a.cond2 = b.cond2 and a.cond3 = b.cond3 or
             a.cond4 = b.cond4
            )
      order by (a.cond2 = b.cond2 and a.cond3 = b.cond3) desc
      limit 1 desc
     ) b
     on 1=1

否则,您可以这样表述:

select *
from table1 a left join lateral
     (select b.*,
             rank() over (order by (a.cond2 = b.cond2 and a.cond3 = b.cond3) desc) as seqnum
      from table2 b
      where a.cond1 = b.cond1 and
            (a.cond2 = b.cond2 and a.cond3 = b.cond3 or
             a.cond4 = b.cond4
            )
     ) b
     on b.seqnum = 1;

【讨论】:

    【解决方案3】:

    由于您似乎只想找到第一个匹配项,因此您可以通过以下方式获得:

    select a.id,b.tag       
       from table1 a join table2 b on a.cond1 = b.cond1
      where (   (a.cond2 = b.cond2 and a.cond3 = b.cond3)
             or (a.cond4 = b.cond4)
            )
      order by a.id
      limit 1;
    

    只是关于表格别名的一个(我的烦恼)快速说明。选择一个直观的值。在这种情况下,t1 和 t2 将比 a 和 b 更多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-31
      • 2018-05-31
      • 1970-01-01
      • 2016-10-09
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2020-09-19
      相关资源
      最近更新 更多