访问主 table 字段的子查询与 Oracle SQL 中的 LIMIT 子句相结合
Subquery that accesses main table fields combined with LIMIT clause in Oracle SQL
我有一个 table 用户和一个 table 任务。任务按重要性排序并分配给用户的任务列表。任务有一个状态:就绪或未就绪。现在,我想列出所有用户,他们最重要的任务也已准备就绪。
首先需要对每个用户的任务进行筛选和排序,然后选择最重要的任务,这是一个有趣的要求。这是我想出的:
SELECT Users.name,
(SELECT *
FROM (SELECT Tasks.description
FROM Tasks
WHERE Tasks.taskListCode = Users.taskListCode AND Tasks.isReady
ORDER BY Tasks.importance DESC)
WHERE rownum = 1
) AS nextTask
FROM Users
但是,这会导致错误
ORA-00904: "Users"."taskListCode": invalid identifier
我认为原因是oracle does not support correlating subqueries with more than one level of depth。但是,我需要两个级别才能执行 WHERE rownum = 1
.
我也试过没有关联子查询:
SELECT Users.name, Task.description
FROM Users
LEFT JOIN Tasks nextTask ON
nextTask.taskListCode = Users.taskListCode AND
nextTask.importance = MAX(
SELECT tasks.importance
FROM tasks
WHERE tasks.isReady
GROUP BY tasks.id
)
这会导致错误
ORA-00934: group function is not allowed here
我该如何解决这个问题?
请尝试解析函数:
with tp as (select t.*, row_number() over (partition by taskListCode order by importance desc) r
from tasks t
where isReady = 1 /*or 'Y' or what is positive value here*/)
select u.name, tp.description
from users u left outer join tp on (u.taskListCode = tp.taskListCode)
where tp.r = 1;
一个解决方法是使用 keep
:
SELECT u.name,
(SELECT MAX(t.description) KEEP (DENSE_RANK FIRST ORDER BY T.importance DESC)
FROM Tasks t
WHERE t.taskListCode = u.taskListCode AND t.isReady
) as nextTask
FROM Users u;
这是一个使用聚合而不是分析函数的解决方案。您可能希望 运行 将其与解析函数解决方案进行比较,以查看哪个更快;在许多情况下,聚合查询(稍微)更快,但这取决于您的数据、索引使用等。
这个解决方案与 Gordon 尝试做的类似。我不知道他为什么使用相关子查询而不是直接连接来编写它(并且不知道它是否有效 - 我从未见过 FIRST/LAST 函数与这样的相关子查询一起使用)。
如果 importance
列中可能有 NULL
,它可能无法正常工作 - 那么您需要在 t.importance
之后和 [= 之前添加 nulls first
15=]。注意:max(t.description)
是必需的,因为 "importance" 可能存在联系(两个任务对于给定用户具有相同的、最重要的)。在这种情况下,必须选择一项任务。如果按重要性排序是严格的(没有关系),那么 MAX()
什么都不做,因为它在一组恰好一个值上选择 MAX,但编译器事先不知道,所以它确实需要 MAX()
.
select u.name,
max(t.description) keep (dense_rank last order by t.importance) as descr
from users u left outer join tasks t on u.tasklistcode = t.tasklistcode
where t.isready = 'Y'
group by u.name
我有一个 table 用户和一个 table 任务。任务按重要性排序并分配给用户的任务列表。任务有一个状态:就绪或未就绪。现在,我想列出所有用户,他们最重要的任务也已准备就绪。
首先需要对每个用户的任务进行筛选和排序,然后选择最重要的任务,这是一个有趣的要求。这是我想出的:
SELECT Users.name,
(SELECT *
FROM (SELECT Tasks.description
FROM Tasks
WHERE Tasks.taskListCode = Users.taskListCode AND Tasks.isReady
ORDER BY Tasks.importance DESC)
WHERE rownum = 1
) AS nextTask
FROM Users
但是,这会导致错误
ORA-00904: "Users"."taskListCode": invalid identifier
我认为原因是oracle does not support correlating subqueries with more than one level of depth。但是,我需要两个级别才能执行 WHERE rownum = 1
.
我也试过没有关联子查询:
SELECT Users.name, Task.description
FROM Users
LEFT JOIN Tasks nextTask ON
nextTask.taskListCode = Users.taskListCode AND
nextTask.importance = MAX(
SELECT tasks.importance
FROM tasks
WHERE tasks.isReady
GROUP BY tasks.id
)
这会导致错误
ORA-00934: group function is not allowed here
我该如何解决这个问题?
请尝试解析函数:
with tp as (select t.*, row_number() over (partition by taskListCode order by importance desc) r
from tasks t
where isReady = 1 /*or 'Y' or what is positive value here*/)
select u.name, tp.description
from users u left outer join tp on (u.taskListCode = tp.taskListCode)
where tp.r = 1;
一个解决方法是使用 keep
:
SELECT u.name,
(SELECT MAX(t.description) KEEP (DENSE_RANK FIRST ORDER BY T.importance DESC)
FROM Tasks t
WHERE t.taskListCode = u.taskListCode AND t.isReady
) as nextTask
FROM Users u;
这是一个使用聚合而不是分析函数的解决方案。您可能希望 运行 将其与解析函数解决方案进行比较,以查看哪个更快;在许多情况下,聚合查询(稍微)更快,但这取决于您的数据、索引使用等。
这个解决方案与 Gordon 尝试做的类似。我不知道他为什么使用相关子查询而不是直接连接来编写它(并且不知道它是否有效 - 我从未见过 FIRST/LAST 函数与这样的相关子查询一起使用)。
如果 importance
列中可能有 NULL
,它可能无法正常工作 - 那么您需要在 t.importance
之后和 [= 之前添加 nulls first
15=]。注意:max(t.description)
是必需的,因为 "importance" 可能存在联系(两个任务对于给定用户具有相同的、最重要的)。在这种情况下,必须选择一项任务。如果按重要性排序是严格的(没有关系),那么 MAX()
什么都不做,因为它在一组恰好一个值上选择 MAX,但编译器事先不知道,所以它确实需要 MAX()
.
select u.name,
max(t.description) keep (dense_rank last order by t.importance) as descr
from users u left outer join tasks t on u.tasklistcode = t.tasklistcode
where t.isready = 'Y'
group by u.name