我在一对多关系中有两列。我想对“很多”进行排序并返回第一次出现的“one”。我需要翻阅数据,所以,例如,我需要能够获得第3组10个唯一的“一”值。
我有这样的查询:
SELECT id, name
FROM table1
INNER JOIN table2 ON table2.fkid = table1.id
ORDER BY name, id;
table1中每行可以有多行。
我的查询结果如下:
id | name
----------------
2 | apple
23 | banana
77 | cranberry
23 | dark chocolate
8 | egg
2 | yak
19 | zebra
我需要在每个包含n 唯一 ID的页面中翻阅结果集。例如,如果start = 1且n = 4,我想回来
2
23
77
8
按照它们的排序顺序(即名称),其中id在第一次出现的位置返回。同样,如果start = 3且n = 4并且order = desc我想要
8
23
77
2
我试过了:
SELECT * FROM (
SELECT id, ROWNUM rnum FROM (
SELECT DISTINCT id FROM (
SELECT id, name
FROM table1
INNER JOIN table2 ON table2.fkid = table1.id
ORDER BY name, id)
WHERE ROWNUM <= 4)
WHERE rnum >=1)
以数字顺序给出了id,而不是按名称命令。
我也尝试过:
SELECT * FROM (
SELECT DISTINCT id, ROWNUM rnum FROM (
SELECT id FROM (
SELECT id, name
FROM table1
INNER JOIN table2 ON table2.fkid = table1.id
ORDER BY name, id)
WHERE ROWNUM <= 4)
WHERE rnum >=1)
但这给了我重复的值。
如何浏览此数据的结果?我只需要ids,而不是“很多”表。
更新
我想我正在接近将内部查询更改为
SELECT id, name, rank() over (order by name, id)
FROM table1
INNER JOIN table2 ON table2.fkid = table1.id
...但我仍然会收到重复的ID。
答案 0 :(得分:1)
您可能需要稍微调试一下,但它会是这样的:
SELECT * FROM (
SELECT * FROM (
SELECT id FROM (
SELECT id, name, row_number() over (partition by id order by name) rn
FROM table1
INNER JOIN table2 ON table2.fkid = table1.id
)
) WHERE rn=1 ORDER BY name, id
) WHERE rownum>=1 and rownum<=4;
答案 1 :(得分:0)
这有点令人费解(我倾向于怀疑它可以简化)但它应该有效。你可以在WHERE
子句中放置你想要的任何开始和结束位置 - 我在这里展示的是start = 2和n = 4是从一个单独的表中提取的,但是你可以通过使用一对来简化事情而是参数。
SQL> ed
Wrote file afiedt.buf
1 with t as (
2 select 2 id, 'apple' name from dual union all
3 select 23, 'banana' from dual union all
4 select 77, 'cranberry' from dual union all
5 select 23, 'dark chocolate' from dual union all
6 select 8, 'egg' from dual union all
7 select 2, 'yak' from dual union all
8 select 19, 'zebra' from dual
9 ),
10 x as (
11 select 2 start_pos, 4 n from dual
12 )
13 select *
14 from (
15 select distinct
16 id,
17 dense_rank() over (order by min_id_rnk) outer_rnk
18 from (
19 select id,
20 min(rnk) over (partition by id) min_id_rnk
21 from (
22 select id,
23 name,
24 rank() over (order by name) rnk
25 from t
26 )
27 )
28 )
29 where outer_rnk between (select start_pos from x) and (select start_pos+n-1 from x)
30* order by outer_rnk
SQL> /
ID OUTER_RNK
---------- ----------
23 2
77 3
8 4
19 5