caz*_*zer 8 sql oracle select oracle10g
我有一个表可能包含三种不同的文件类型.如果存在文件类型A,则选择A,否则如果存在文件类型B并且没有具有相同client_id的类型Cs,则选择B,否则选择类型C.
稍后将发生一些其他魔术将从中删除所选文件表.
我在Oracle 10g SQL数据库中有以下表:
ID | TYPE | CLIENT_ID
########################
file1 | A | 1
file2 | B | 1
file3 | C | 1
file4 | B | 2
Run Code Online (Sandbox Code Playgroud)
对于那些想在家里跟随的人,sqlfidde或sql:
create table files (
id varchar(8) primary key,
type varchar(4),
client_id number
);
insert into files values ('file1', 'A', 1);
insert into files values ('file2', 'B', 1);
insert into files values ('file3', 'C', 1);
insert into files values ('file4', 'B', 2);
Run Code Online (Sandbox Code Playgroud)
我希望创建一个讨厌的大查询来根据上面的标准获取下一个文件,如果查询运行四次,应该产生以下顺序:
#1: file1, A, 1 (grab any As first)
#2: file4, B, 2 (grab any Bs who don't have any Cs with the same client_id)
#3: file3, C, 1 (grab any Cs)
#4: file2, B, 1 (same as run #2)
Run Code Online (Sandbox Code Playgroud)
让我最远的尝试是为每种类型写三个单独的查询:
--file type 'A' selector
select * from files where type = 'A'
--file type 'B' selector
select * from files where type = 'B' and client_id = (
select client_id from files group by client_id having count(*) = 1
);
--file type 'C' selector
select * from files where type = 'C'
Run Code Online (Sandbox Code Playgroud)
我想检查每个之后返回的行数,如果它是0则使用下一个select,但是在一个SQL语句中.
您可以使用一些嵌套分析,虽然这看起来比它可能应该更复杂:
select id, type, client_id
from (
select t.*,
case when type = 'a'then 1
when type = 'b' and c_count = 0 then 2
when type = 'c' then 3
end as rnk
from (
select f.*,
sum(case when type = 'a' then 1 else 0 end)
over (partition by client_id) as a_count,
sum(case when type = 'b' then 1 else 0 end)
over (partition by client_id) as b_count,
sum(case when type = 'c' then 1 else 0 end)
over (partition by client_id) as c_count
from files f
) t
)
order by rnk;
Run Code Online (Sandbox Code Playgroud)
SQL Fiddle显示了如何构建最终结果.
或者可能更好一点,这次只拉一条记录,我认为是循环内的最终目标(?):
select id, type, client_id
from (
select t.*,
dense_rank() over (
order by case when type = 'a' then 1
when type = 'b' and c_count = 0 then 2
when type = 'c' then 3
end, client_id) as rnk
from (
select f.*,
sum(case when type = 'c' then 1 else 0 end)
over (partition by client_id) as c_count
from files f
) t
)
where rnk = 1;
Run Code Online (Sandbox Code Playgroud)
更新了SQL小提琴,显示再次工作,因此您可以看到评估的顺序是您要求的.
无论哪种方式,这只能击中桌子一次,这可能是一个优势,但必须扫描整个事情,这可能不是......