【问题标题】:CASE WHEN is giving 2 rows with duplicate IDCASE WHEN 给出 2 行重复 ID
【发布时间】:2018-04-04 19:28:41
【问题描述】:

我写了一个查询,它会产生如下结果。

select t1.id as id,
CASE
    WHEN t3.key_id is not null and t3.key_id='SILICA'
    THEN t3.id
    END as SILICA_ID,
CASE
    WHEN t3.key_id is not null and t3.key_id='Mutual'
    THEN t3.id
    END as Mutual_ID
from table1 t1, table2 t2, table3 t3 
where t1.id=t2.t1_id and t2.id=t3.t2_id and t3.key_id in ('SILICA','Mutual') 
order by t1.id;
id SILICA_ID Mutual_id == ========= ========= 1 空 1234 1 3456 空 2 空 7890 2 2374 空 2 4587 空 2 空 3489

但是,我需要如下结果。

id SILICA_ID Mutual_id == ========= ========= 1 3456 1234 2 2345 7890 2 4587 3489

我怎样才能做到这一点?

提前致谢

【问题讨论】:

  • 不要使用逗号分隔的列表作为 from 子句。 25 多年前,人们采用了一个更好的标准。就连这银鬼也有足够的时间来改变。 trincot 的回答显示了更好的连接语法
  • 来自 table t1, table t2, table t3 ?这是什么意思?这总是同一张桌子吗?
  • 都是不同的表。
  • 好的。现在请编辑您的请求。到目前为止,您正在显示一个查询结果,其中 id 1 有两条记录,id 2 有两条记录,以及您真正想要的结果(id 1 一行,id 2 一行)。请为 id 1 显示更多行的查询结果,并再次显示相应的所需结果。或者更好地提出一个新的请求,因为你已经得到了正确的答案,甚至接受了其中一个。
  • 这些是奇怪的必需结果。为什么要将二氧化硅 2345 与互惠 7890 以及二氧化硅 4587 与互惠 3489 结合使用?例如,为什么不使用硅胶 2345 和相互 3489?您在这里应用的关系规则是什么?

标签: sql oracle


【解决方案1】:

每个t1 可以有多个t2,每个t2 可以有多个t3。但是您希望每个 t1.id 有一个结果行。所以你想聚合你的数据。

您的结果仅显示每个t1.idt3.key_id 一个t3.id。这是出乎意料的,表明数据模型错误或样本数据不足。

无论如何,为了每个t1.id 聚合每个t1.id 获得一个结果行并使用条件聚合:

select t1.id as id,
  max(case when t3.key_id = 'SILICA' THEN t3.id end) as silica_id,
  max(case when t3.key_id = 'Mutual' then t3.id end) as mutual_id
from t1
join t2 on t2.t1_id = t1.id 
join t3 on t3.t2_id = t2.id and t3.key_id in ('SILICA','Mutual') 
group by t1.id
order by t1.id;

更新:您更改的请求显示结果行,其中 SILICA/Mutual 对似乎没有直接关系。您似乎更想以类似报纸的方式列出它们。您可以通过分别选择“SILICA”和“Mutual”来执行此操作,为它们提供行号并加入这些行号。

select t1_id, s.t3_id as silica_id, m.t3_id as mutual_id 
  t1.id as t1_id, 
    t3.id as t3_id
(
  select distinct 
    t1.id as t1_id, 
    t3.id as t3_id,
    row_number() over (partition by t1.id order by t3.id) as rn
  from t1
  join t2 on t2.t1_id = t1.id 
  join t3 on t3.t2_id = t2.id and t3.key_id = 'SILICA'
) s
full outer join
(
  select distinct 
    t1.id as t1_id, 
    t3.id as t3_id,
    row_number() over (partition by t1.id order by t3.id) as rn
  from t1
  join t2 on t2.t1_id = t1.id 
  join t3 on t3.t2_id = t2.id and t3.key_id = 'Mutual'
) m using (t1_id, rn);

【讨论】:

  • 如果我使用 max 函数,我可能会丢失一些其他的最小记录。你能告诉我没有 max 函数吗?
  • 请看我修改后的答案。我想新的查询就是你要找的。​​span>
【解决方案2】:

您可以为此使用pivot 语法:

select *
from   (
      select     t1.id, 
                 t3.id as t3_id, 
                 t3.key_id
      from       tabl t1
      inner join tabl t2 on t1.id = t2.t1_id
      inner join tabl t3 on t2.id = t3.t2_id
      where      t3.key_id in ('SILICA', 'Mutual')
) pivot (
      max(t3_id)
      for key_id in ('SILICA' as silica_id, 'Mutual' as mutual_id)
);

注意:使用join 子句来表达连接条件是一个好习惯,而不是将它们放在where 子句中。

【讨论】:

  • 非常感谢您的回复。你能在没有 max() 函数的情况下调整这个查询吗?
  • 透视语法需要聚合。它提供与您接受的答案相同的输出(除非我弄错了)。整个想法是id 在输出中应该是唯一的。如果不是,则存在歧义,然后我会要求您提供示例数据和输出以显示您希望它如何工作。
【解决方案3】:

您需要一个聚合解决方案,例如

select id
       , max(silica_id) as silica_id
       , max(Mutual_ID) as Mutual_ID
from (
    select t1.id as id,
    CASE
        WHEN t3.key_id is not null and t3.key_id='SILICA'
        THEN t3.id
        END as SILICA_ID,
    CASE
        WHEN t3.key_id is not null and t3.key_id='Mutual'
        THEN t3.id
        END as Mutual_ID
    from table t1, table t2, table t3 
    where t1.id=t2.t1_id and t2.id=t3.t2_id and t3.key_id in ('SILICA','Mutual')
    ) 
group by id
order by id;

【讨论】:

  • 感谢您对此的宝贵回复。但是, max(silica_id) 将为此返回最大 id。例如,如果我们有 4 行包含关于 id 的内容,那么 max(silica_id) 将仅返回对应于该 ID 的最大值。
  • @Pamuleti Pullagura:您的样本数据表明每个t1.id 始终只有一个silica_id,因此max(silica_id) 将得到这个值。如果情况并非总是如此,您应该使用两个不同的silica_idt1.id = 1 编辑样本数据,然后向我们展示您想要的结果。
  • 每个t1.id 有多个silica_id,每个t1.id 有多个mutual_id。这就是问题所在。“您应该使用t1.id = 1 的两个不同silica_id 编辑样本数据并显示我们然后你想要什么结果“..你到底在说什么?你能解释一下吗?
  • 您抱怨我的解决方案不能满足您的需求。因此,请发布完整准确反映您的情况的数据。使用更好的原始数据编辑您的问题并修改所需的输出,以便我们了解您想要什么。
  • 您的解决方案对我有用。我没有抱怨任何事情。但是,不使用 max 函数还有其他解决方案吗?根据您的要求,我已经编辑了我的查询。
猜你喜欢
  • 2023-03-25
  • 1970-01-01
  • 2011-01-01
  • 2016-01-02
  • 2020-11-14
  • 1970-01-01
  • 2014-08-25
  • 2023-03-17
相关资源
最近更新 更多