简体   繁体   English

子查询访问主表字段并结合Oracle SQL中的LIMIT子句

[英]Subquery that accesses main table fields combined with LIMIT clause in Oracle SQL

I got a table Users and a table Tasks. 我有一个表Users和一个表Tasks。 Tasks are ordered by importance and are assigned to a user's task list. 任务按重要性排序,并分配给用户的任务列表。 Tasks have a status: ready or not ready. 任务的状态为:就绪或未就绪。 Now, I want to list all users with their most important task that is also ready. 现在,我想列出所有准备就绪的最重要任务的用户。

The interesting requirement that the tasks for each user first need to be filtered and sorted, and then the most important one should be selected. 有趣的要求是,首先需要对每个用户的任务进行过滤和排序,然后再选择最重要的任务。 This is what I came up with: 这是我想出的:

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

However, this results in the error 但是,这会导致错误

ORA-00904: "Users"."taskListCode": invalid identifier

I think the reason is that oracle does not support correlating subqueries with more than one level of depth . 我认为原因是oracle不支持将关联子查询关联到一个以上的深度 However, I need two levels so that I can do the WHERE rownum = 1 . 但是,我需要两个级别,以便可以执行WHERE rownum = 1

I also tried it without a correlating subquery: 我也尝试了没有相关子查询的情况:

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
    )

This results in the error 这导致错误

ORA-00934: group function is not allowed here

How would I solve the problem? 我该如何解决这个问题?

One work-around for this uses keep : 一个变通为此使用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;

Please try with analytic function: 请尝试使用解析功能:

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;

Here is a solution that uses aggregation rather than analytic functions. 这是一个使用聚合而不是分析函数的解决方案。 You may want to run this against the analytic functions solution to see which is faster; 您可能要针对解析函数解决方案运行此命令,以查看哪种方法更快。 in many cases aggregate queries are (slightly) faster, but it depends on your data, on index usage, etc. 在许多情况下,聚合查询的速度(略)更快,但这取决于您的数据,索引的使用情况等。

This solution is similar to what Gordon tried to do. 此解决方案类似于戈登尝试做的事情。 I don't know why he wrote it using a correlated subquery instead of a straight join (and don't know if it will work - I've never seen the FIRST/LAST function used with correlated subqueries like that). 我不知道他为什么使用相关子查询而不是直接联接来编写它(也不知道它是否会工作-我从未见过FIRST / LAST函数用于这样的相关子查询)。

It may not work exactly right if there may be NULL in the importance column - then you will need to add nulls first after t.importance and before ) . 它可能不完全正确的工作,如果有可能是NULLimportance列-那么你将需要添加nulls firstt.importance之前) Note: the max(t.description) is needed, because there may be ties by "importance" (two tasks with the same, highest importance for a given user). 注意: max(t.description)是必需的,因为可能有“重要性”联系(对于给定用户,两个任务具有相同的,最高的重要性)。 In that case, one task must be chosen. 在这种情况下,必须选择一项任务。 If the ordering by importance is strict (no ties), then the MAX() does nothing as it selects the MAX over a set of exactly one value, but the compiler doesn't know that beforehand so it does need the MAX() . 如果按重要性排序是严格的(无约束),则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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM