微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Teradata SQL 助手 - NOT EXISTS、INNER JOIN、IN 或其他方式

如何解决Teradata SQL 助手 - NOT EXISTS、INNER JOIN、IN 或其他方式

有一张关于汽车的数据表。

model_id 颜色
1 黑色
1 绿色
2 黑色
3 蓝色
3 白色
4 红色
5 白色
5 黑色

任务是,如果模型可以是黑色的,那么只留下它(黑色),如果模型不能是黑色的,那么留下它的所有颜色:

model_id 颜色
1 黑色
2 黑色
3 蓝色
3 白色
4 红色
5 黑色

第一种方式:

create table black_cars as

(select * from cars where color = 'black')

with data;

create table not_black_cars as (

select c.* from cars as c

where not exists (select 1 from black_cars as bc where bc.model_id = c.model_id)

with data;

select * from black_cars

union

select * from not_black_cars;

第二种方式:

select * from cars where color = 'black

union

select * from cars as c

inner join

(select distinct model_id from cars except select model_id from cars where color = 'black') as nbc

on c.model_id = nbc.model_id

第三种方式(低性能):

select * from cars where color = 'black

union

select * from cars where model_id not in

(select model_id from cars where color = 'black)

我不确定这两种方式中的任何一种是最佳的。如果有人能提出最好的方法,我将不胜感激。

解决方法

我会简单地使用:

select c.*
from cars c
where c.color = 'black' or
      not exists (select 1
                  from cars c2
                  where c2.model_id = c.model_id and
                        c2.color = 'black'
                 );

在很多情况下,您可能会发现窗口函数具有良好的性能:

select c.*
from cars c
qualify c.color = 'black' or
        sum(case when c.color = 'black' then 1 else 0 end) over (partition by c.model_id) = 0;

至于所有版本中哪个版本的性能最好——您必须在您的数据和系统上试用它们。这取决于许多因素:

  • 表上的索引。
  • 桌子的大小。
  • 每个模型的平均颜色数。
  • 模型中黑色/非黑色的数量分布。

而且可能更多。以上之一似乎是合理的——不涉及临时表的方法也是如此。

,

这是另一种基于 OLAP 函数的方法,可以轻松扩展到更复杂的逻辑:

SELECT *
FROM cars
QUALIFY
   Rank() 
   Over (PARTITION BY model_id
         -- preferred condition first
         ORDER BY CASE WHEN color = 'black' THEN 1 ELSE 0 END DESC) = 1
;

Teradata 中 OLAP 函数的性能可能与基于 EXISTS 等的解决方案一样好或更好。只有 PARTITION BY 列上的 PI 可能会超过它,主要取决于每个值的行数。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。