我有一个带有'Name','Flag'和其他一些列的表。我想从表中选择特定的行组。数据已根据另一个时间戳列进行排序。
Name Flag
------ ------
A D
B D
C D
D I
E I
D D
E D
B I
D I
F I
我想获取第一组'D'标志和最后一组'I'标志。是否有可能在SQL
(只有选择语句,而不是PL/SQL
)?
期望的输出:
Name Flag
------ ------
A D
B D
C D
B I
D I
F I
答案 0 :(得分:1)
SQL表代表无序集。所以,没有"第一"或者"最后",除非你有一个指定排序的列。请注意,这适用于SQL查询和PL / SQL代码。当然,您指定您有两列,因此数据中不存在此类列。
但我要假设你确实有一个。如果是这样,你可以这样做:
select t.*
from t
where (t.flag = 'D' and
t.orderingcol < (select min(t2.orderingcol) from t t2 where t2.flag <> 'D'
) or
(t.flag = 'I' and
t.orderingcol > (select max(t2.orderingcol) from t t2 where t2.flag <> 'I'
)
order by t.orderingcol;
答案 1 :(得分:1)
假设你有一些确定结果集排序的列(例如下面我的查询中的id列),这很容易用Tabibitosan的技术来做:
WITH sample_data AS (SELECT 1 ID, 'A' NAME, 'D' flag FROM dual UNION ALL
SELECT 2 ID, 'B' NAME, 'D' flag FROM dual UNION ALL
SELECT 3 ID, 'C' NAME, 'D' flag FROM dual UNION ALL
SELECT 4 ID, 'D' NAME, 'I' flag FROM dual UNION ALL
SELECT 5 ID, 'E' NAME, 'I' flag FROM dual UNION ALL
SELECT 6 ID, 'D' NAME, 'D' flag FROM dual UNION ALL
SELECT 7 ID, 'E' NAME, 'D' flag FROM dual UNION ALL
SELECT 8 ID, 'B' NAME, 'I' flag FROM dual UNION ALL
SELECT 9 ID, 'D' NAME, 'I' flag FROM dual UNION ALL
SELECT 10 ID, 'F' NAME, 'I' flag FROM dual)
SELECT ID,
NAME,
flag
FROM (SELECT ID,
NAME,
flag,
grp,
MIN(CASE WHEN flag = 'D' THEN grp END) OVER (PARTITION BY flag) min_d_grp,
MAX(CASE WHEN flag = 'I' THEN grp END) OVER (PARTITION BY flag) max_i_grp
FROM (SELECT ID,
NAME,
flag,
row_number() OVER (ORDER BY ID) - row_number() OVER (PARTITION BY flag ORDER BY ID) grp
FROM sample_data
WHERE flag IN ('D', 'I')))
WHERE (flag = 'D' AND grp = min_d_grp)
OR (flag = 'I' AND grp = max_i_grp)
ORDER BY id;
ID NAME FLAG
---------- ---- ----
1 A D
3 C D
2 B D
9 D I
8 B I
10 F I
此查询使用tabibitosan方法生成一个额外的“grp”列,然后您可以使用该列查找D标志行的最低编号和I标记行的最高编号。
ETA:这可能会或可能不会比Gordon的回答更好,但我建议您测试两个答案,看看哪个更适合您的表/索引/数据等。