0

我在一个简单的表中有以下数据:

ID | TYPE
---------
1  | 1
1  | 2
2  | 1
3  | 2
4  | 1
4  | 2
4  | 3
5  | 1
5  | 3
6  | 3

我现在需要通过以下方式查询这些数据:

  • 对于每个 ID,应该只返回一行
    • 如果 ID 只有一行,则返回它。
    • 如果 ID 有多行,则返回 TYPE = 2 的行。如果不存在,则返回 TYPE = 3 的行。
  • TYPE 可以是 1、2 或 3
  • ID 和 TYPE 有一个复合唯一索引,这意味着每个 ID 最多可以有三行。

问题:我如何将这个逻辑放在查询中?


预期结果:

ID | TYPE
---------
1  | 2
2  | 1
3  | 2
4  | 2
5  | 3
6  | 3
4

8 回答 8

2

Oracle 在所有最新版本中都具有分析功能。

WITH
  sequenced AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY id
                           ORDER BY CASE type WHEN 2 THEN 1
                                              WHEN 3 THEN 2
                                              WHEN 1 THEN 3 END) AS sequenced_id
  FROM
    yourTable
)
SELECT
  *
FROM
  sequenced
WHERE
  sequence_id = 1

使用此技术,您将返回表中的所有值,而不仅仅是 PrimaryKey 和搜索值。

编辑:

处理这个问题的最好方法是拥有另一个表,该表具有每种类型的优先顺序。

 type | preference_value
------+------------------
  2   |         1
  3   |         2
  1   |         3

这表明这2是最优先的,3是第二优先的,1是第三优先的。

然而,因为它是一个很小的群体,它也可以只用一个简单的CASE语句来完成。请参阅上面我修改后的查询。

于 2012-08-20T15:00:17.600 回答
2

这是我的看法:http ://www.sqlfiddle.com/#!4/9957d/4

select id, 
    case when sum(case when type = 2 then 1 end) = 1 then
       2
    else
       max(type)
    end   
from tbl
group by id
order by id

输出:

| ID | TYPE |
-------------
|  1 |    2 |
|  2 |    1 |
|  3 |    2 |
|  4 |    2 |
|  5 |    3 |
|  6 |    3 |
于 2012-08-20T15:16:08.793 回答
2

另一种方法,最小化 CASE WHEN 分支:http ://www.sqlfiddle.com/#!4/9957d/17

select id, 

    coalesce( sum(case when type=2 then 2 end), max(type) ) as type

from tbl
group by id
order by id

输出:

| ID | TYPE |
-------------
|  1 |    2 |
|  2 |    1 |
|  3 |    2 |
|  4 |    2 |
|  5 |    3 |
|  6 |    3 |
于 2012-08-20T15:30:03.373 回答
1

由于您知道没有TYPE高于 2 的值,因此您可以这样做:

select ID, max(TYPE) as TYPE
from MyTable
group by ID
于 2012-08-20T14:58:59.850 回答
1

试试这个

select id, type from
(
   select *, ROW_NUMBER() over (partition by id order by abs(2.25-type) ) as rn
   from yourtable
)v
where rn=1
于 2012-08-20T15:06:34.527 回答
1

我会使用一个小技巧。

SELECT ID, IF(SUM(TYPE) IN (5, 6), 2, MAX(TYPE)) AS TYPE
FROM table
GROUP BY ID
于 2012-08-20T15:11:59.890 回答
1

玩转MOD()功能:

SELECT 
    id,
    MOD(MIN(MOD(type+1,3))+1,3)+1 AS type
FROM
    tableX
GROUP BY
    id ;
于 2012-08-20T15:22:04.540 回答
0

根据 podiluska 和 Dems 的建议,我现在使用这个:

with type_order as
(
    select 1 as type, 0 as prio from dual
    union all
    select 2 as type, 2 as prio from dual
    union all
    select 3 as type, 1 as prio from dual
)
select id, type from 
( 
   select yt.*, ROW_NUMBER() over (partition by id order by o.prio desc) as rn 
   from yourtable yt
   inner join type_order o on yt.type = o.type
)v 
where rn=1 

这是非常明确的意图并且易于扩展。如果以后有更多的类型,这个type_order内联视图可以重构为一个真实的表格。

于 2012-08-20T15:29:00.660 回答