SQL - 如果参数存在则显示一行,否则显示另一个参数(如果存在)

时间:2011-10-11 16:29:57

标签: sql oracle

我有一张如下表格:

ID  |INFO     | DATE_DT
-------------------------
1091|info5    |10/10/2010
1239|old.info |14/09/2010
1340|old.info |07/10/2010
3481|info     |16/10/2010
4134|info3    |21/01/2011

我想在以下条件下只显示一行:
- 如果我在我的表格中有一行INFO = 'info' - >只显示这一行
- 如果我没有INFO = 'info'行,那么i - >显示INFO = 'old.info'DATE_DT = MAX(DATE_DT)

所以,在我的例子中,如果我的表是:

ID  |INFO     | DATE_DT
-------------------------
1091|info5    |10/10/2010
1239|old.info |14/09/2010
1340|old.info |07/10/2010
3481|info     |16/10/2010 ===> display this row
4134|info3    |21/01/2011

或者如果我的表格不包含INFO ='info'

ID  |INFO     | DATE_DT
-------------------------
1091|info5    |10/10/2010
1239|old.info |14/09/2010
1340|old.info |07/10/2010 ===> display this row
4134|info3    |21/01/2011

有什么建议吗?

感谢。

2 个答案:

答案 0 :(得分:3)

您可以选择两个行,并按优先级选择满足第一个条件的行:

SQL> WITH my_table AS (
  2  SELECT 1091 id, 'info5' info, to_date('10/10/2010') date_dt FROM DUAL
  3  UNION ALL SELECT 1239, 'old.info' , to_date('14/09/2010') FROM DUAL
  4  UNION ALL SELECT 1340, 'old.info' , to_date('07/10/2010') FROM DUAL
  5  UNION ALL SELECT 3481, 'info'     , to_date('16/10/2010') FROM DUAL
  6  UNION ALL SELECT 4134, 'info3'    , to_date('21/01/2011') FROM DUAL)
  7  SELECT * FROM (
  8     SELECT 1 ord, t.*
  9       FROM my_table t
 10      WHERE info = 'info'
 11     UNION ALL
 12     SELECT 2 ord, t.*
 13       FROM my_table t
 14      WHERE date_dt = (SELECT MAX(date_dt) FROM my_table)
 15     ORDER BY ord)
 16   WHERE ROWNUM = 1;

       ORD         ID INFO     DATE_DT
---------- ---------- -------- -----------
         1       3481 info     16/10/2010

如果您删除行'info',则会选择DATE_DT = MAX(DATE_DT)行:

SQL> WITH my_table AS (
  2  SELECT 1091 id, 'info5' info, to_date('10/10/2010') date_dt FROM DUAL
  3  UNION ALL SELECT 1239, 'old.info' , to_date('14/09/2010') FROM DUAL
  4  UNION ALL SELECT 1340, 'old.info' , to_date('07/10/2010') FROM DUAL
  5  /*UNION ALL SELECT 3481, 'info'     , to_date('16/10/2010') FROM DUAL*/
  6  UNION ALL SELECT 4134, 'info3'    , to_date('21/01/2011') FROM DUAL)
  7  SELECT * FROM (
  8     SELECT 1 ord, t.*
  9       FROM my_table t
 10      WHERE info = 'info'
 11     UNION ALL
 12     SELECT 2 ord, t.*
 13       FROM my_table t
 14      WHERE date_dt = (SELECT MAX(date_dt) FROM my_table)
 15     ORDER BY ord)
 16   WHERE ROWNUM = 1;

       ORD         ID INFO     DATE_DT
---------- ---------- -------- -----------
         2       4134 info3    21/01/2011

答案 1 :(得分:2)

您也可以使用analytic functions执行此操作,只需要对数据进行一次传递:

with my_tab as (
select 1091 as id, 'info5' as info, to_date('10/10/2010',' DD/MM/YYYY') as date_dt from dual
union all select 1239, 'old.info', to_date('14/09/2010', 'DD/MM/YYYY') from dual
union all select 1340, 'old.info', to_date('07/10/2010', 'DD/MM/YYYY') from dual
union all select 3481, 'info', to_date('16/10/2010', 'DD/MM/YYYY') from dual
union all select 4134, 'info3', to_date('21/01/2011', 'DD/MM/YYYY') from dual
)
select id, info, to_char(date_dt, 'DD/MM/YYYY')
from (
    select id, info, date_dt, rank() over (order by ord, date_dt desc) as rnk
    from (
        select id, info, date_dt,
            case info
                when 'info' then 1
                when 'old.info' then 2
                when 'info3' then 3
                else null
            end as ord
        from my_tab
    )
)
where rnk = 1;

        ID INFO     DATE_DT
---------- -------- ----------
      3481 info     16/10/2010

敲出'info'行给出:

        ID INFO     DATE_DT
---------- -------- ----------
      1340 old.info 07/10/2010

对于这个微不足道的案例,可能没有比@Vincent更好,但是有更多的数据和更多的值可供选择,这可能会更好地扩展 - 只需要更多的ord值,尽管有任何实际数据我会我以为你会从另一张桌子上查找优先权......