【问题标题】:How to put all rows at the same level in SQL?如何在 SQL 中将所有行放在同一级别?
【发布时间】:2022-01-14 10:34:10
【问题描述】:

尝试将此查询用于客户要求贷款的过程:

select loan_id,
CASE WHEN status = 'document_sent' then date ELSE NULL END as document_sent,
CASE WHEN status = 'document_rejected' then date ELSE NULL END as document_rejected
from table
and status in ('document_sent', 'document_rejected')
order by 2 asc, 3 asc

结果如下:

loan_id document_sent doc_rejected
123 2021-03-01 14:52
123 2021-03-01 14:57
123 2021-03-01 15:33
123 2021-03-01 14:54
123 2021-03-01 15:00
123 2021-03-01 15:39

我想要这样的东西:

loan_id document_sent doc_rejected
123 2021-03-01 14:52 2021-03-01 14:54
123 2021-03-01 14:57 2021-03-01 15:00
123 2021-03-01 15:33 2021-03-01 15:39

有可能吗?谢谢

【问题讨论】:

  • 能否也添加原始数据表
  • 查询如何知道要“在同一级别查看”哪些行?它们都是同一个loan_id,所以它们如何结合在一起似乎没有任何逻辑。
  • ELSE NULL 是默认行为。你可以省略它。
  • 这里的每一行都有相同的loan_id。所以没有主表数据是不可能给出答案的。

标签: mysql sql amazon-web-services amazon-athena presto


【解决方案1】:

如果我们不对每种记录的缺失/存在做出任何假设:

select 
 coalesce(a.loan_id,b.loan_id) as loan_id
 , ds.date as document_sent
 , dr.date as document_rejected
from 
   (select * from tbl where status='document_sent') ds
   full outer join
   (select * from tbl where status='document_rejected') dr
   on ds.loan_id=dr.loan_id
   

如果您知道始终存在一种或另一种状态,则可以稍微简化一下(可以转换为left join),或者如果预计两条记录都存在,则可以简化为:

select 
  a.loan_id
 , ds.date as document_sent
 , dr.date as document_rejected
from 
   tbl ds
   inner join
   tbl dr
   on ds.loan_id=dr.loan_id
   and ds.status='document_sent'
   and dr.status='document_rejected'

如果 `full external join 不可用:

select 
 coalesce(a.loan_id,b.loan_id) as loan_id
 , ds.date as document_sent
 , dr.date as document_rejected
from 
   (select * from tbl where status='document_sent') ds
   left join
   (select * from tbl where status='document_rejected') dr
   on ds.loan_id=dr.loan_id
union all
select 
 coalesce(a.loan_id,b.loan_id) as loan_id
 , ds.date as document_sent
 , dr.date as document_rejected
from 
   (select * from tbl where status='document_sent') ds
   right join
   (select * from tbl where status='document_rejected') dr
   on ds.loan_id=dr.loan_id
where ds.loan_id is null

感谢@nbk 指出。

您也可以使用 MIN/MAX(虽然我们不想找到任何东西的最小值/最大值,但我们希望利用它们的行为 1.它们接受日期,2.它们忽略空值,3.它们与GROUP BY 一起使用,将行组合在一起):

select 
  loan_id
 , min(case when status='document_sent' 
            then ds.date else NULL end) as document_sent
 , min(case when status='document_rejected' 
            then ds.date else NULL end) as document_rejected
from 
   tbl
group by id

【讨论】:

  • mysql 没有完全外连接
  • 投反对票的意思是“这个答案没用”(当你将鼠标悬停在向下按钮上时,请参阅提示),这个答案怎么没用?在其原始形式中,它可以像我稍后通过编辑答案演示的那样轻松调整为完全外部连接)?我认为答案没有用,只有在您复制和运行时才有效。
猜你喜欢
  • 2013-02-27
  • 2014-11-02
  • 2022-12-17
  • 2022-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多