oracle 根据列值有条件地选择行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17342005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 01:45:43  来源:igfitidea点击:

Conditional selecting rows based on a column value

sqloracleplsqloracle10g

提问by 03Usr

ID  RANGE_ID            START_DATE    END_DATE    BAND_TYPE           FLAG_LINE
3     1               01/03/2013    31/03/2013          R                   1
4     1               01/03/2013    31/03/2013          R                   0
5     2               01/03/2013    31/03/2013          R                   1
6     2               01/03/2013    31/03/2013          R                   0
7     3               01/03/2013    31/03/2013          R                   0
8     3               01/03/2013    31/03/2013          N                   0

From this table, for each RANGE_ID, I need to select rows using the following conditions: If there are rows with identical columns (apart from the ID field) then only select the row which has FLAG_LINE = 1, if there are identical rows but none of them contain a FLAG_LINE=1 column then select all of them, based on this the query should return the following results:

从这个表中,对于每个 RANGE_ID,我需要使用以下条件选择行:如果有具有相同列的行(除了 ID 字段),那么只选择具有 FLAG_LINE = 1 的行,如果有相同的行但没有其中包含一个 FLAG_LINE=1 列,然后选择所有这些,基于此查询应返回以下结果:

ID  RANGE_ID          START_DATE    END_DATE      BAND_TYPE           FLAG_LINE
3     1               01/03/2013    31/03/2013          R                   1
5     2               01/03/2013    31/03/2013          R                   1
7     3               01/03/2013    31/03/2013          R                   0
8     3               01/03/2013    31/03/2013          N                   0

I tried doing it in chunks: i.e run something similar for each RANGE:

我尝试分块进行:即为每个 RANGE 运行类似的操作:

begin
  for x in ( select count(*) cnt
               from dual 
              where exists (
                select 1 FROM myTable 
                WHERE RANGE_ID = 1 AND FLAG_LINE = 1) )
  loop
        if ( x.cnt = 1 ) 
        then
           dbms_output.put_line('flag line exists');
           --insert the line with FLAG_LINE = 1 into temp table for this range
        else 
           dbms_output.put_line('does not exist');
           --insert the lines into temp table for this range
        end if;
  end loop;
end;

using this method for each RANGE I populate a temp table and return the results at the end, but this is not quite flexible, is there another way that this can be achieved?

对每个 RANGE 使用这种方法我填充一个临时表并在最后返回结果,但这不是很灵活,还有另一种方法可以实现吗?

Thanks

谢谢

回答by Amit Singh

try like this...

像这样尝试...

Select * from tablename where flag=1 
union 
(Select * from tablename a where  (Select count(*) from tablename b 
where a.Range_id=b.RANGE_ID  and b.flag=1)<1)

SQL FIDDLE Demo

SQL 小提琴演示

回答by Noel

Try this.

尝试这个。

select * from myTable
 where flag_line = 1
       or
       (range_id, start_date, end_date, band_type) in (
                  select range_id, start_date, end_date, band_type
                    from myTable
                group by range_id, start_date, end_date, band_type
                  having max(flag_line) = 0)

回答by mtwaddell

Here's another way to get the results you're wanting

这是获得您想要的结果的另一种方法

SELECT *
  FROM info
 WHERE flag_line = 1
UNION
SELECT *
  FROM info i1
 WHERE NOT EXISTS (SELECT NULL
                     FROM info i2
                    WHERE i2.range_id = i1.range_id
                      AND i2.flag_line = 1
                   )