按contractnumber筛选数据:优先取deviceid='all'行,无则取全部
需求说明
对于每个contractnumber,若存在deviceid='all'的行,则仅保留这些行;若不存在deviceid='all'的行,则保留该contractnumber对应的所有行。
原始表结构及数据
| tenant | contractnumber | deviceid | Price | type |
|---|---|---|---|---|
| 1 | 20 | all | 0.05 | 1 |
| 1 | 20 | all | 0.02 | 2 |
| 1 | 20 | all | 0.07 | 3 |
| 1 | 20 | xy7 | 0.03 | 1 |
| 1 | 20 | xy7 | 0.005 | 2 |
| 1 | 20 | xy7 | 0.04 | 3 |
| 1 | 20 | rq9 | 0.05 | 1 |
| 1 | 20 | rq9 | 0.02 | 2 |
| 1 | 25 | am6 | 0.04 | 1 |
| 1 | 25 | am6 | 0.03 | 2 |
| 1 | 25 | am6 | 0.06 | 3 |
期望结果
| tenant | contractnumber | deviceid | Price | type |
|---|---|---|---|---|
| 1 | 20 | all | 0.05 | 1 |
| 1 | 20 | all | 0.02 | 2 |
| 1 | 20 | all | 0.07 | 3 |
| 1 | 25 | am6 | 0.04 | 1 |
| 1 | 25 | am6 | 0.03 | 2 |
| 1 | 25 | am6 | 0.06 | 3 |
解决方案
以下提供两种可行的SQL实现方式:
方式一:使用EXISTS子查询
SELECT t.* FROM your_table t WHERE t.deviceid = 'all' OR NOT EXISTS ( SELECT 1 FROM your_table t2 WHERE t2.contractnumber = t.contractnumber AND t2.deviceid = 'all' );
逻辑:直接筛选出deviceid='all'的行,或者当前contractnumber下没有deviceid='all'记录的所有行。
方式二:使用窗口函数标记
WITH contract_flags AS ( SELECT *, COUNT(CASE WHEN deviceid = 'all' THEN 1 END) OVER (PARTITION BY contractnumber) AS has_all FROM your_table ) SELECT tenant, contractnumber, deviceid, Price, type FROM contract_flags WHERE has_all = 0 OR deviceid = 'all';
逻辑:先通过窗口函数统计每个contractnumber下是否存在deviceid='all'的行(has_all>0表示存在),再筛选出无all记录的所有行,或本身就是deviceid='all'的行。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

