2012-08-08 134 views
2

我一直在使用这个SQL问题约2天,现在怀疑我非常接近解决问题,但似乎无法找到一个解决方案,完全作品。SQL选择与内部联接,子选择和限制

我试图做的是在两个表上选择性连接,称为application_infoapplication_status,用于存储有关开放获取期刊文章资助请求的信息。

application_info具有关于申请人的一般信息,并使用称为Application_ID的自动索引字段作为关键字段。 application_status用于追踪有关申请状态(已收到,正在审阅,资助,拒绝,撤回等)以及期刊文章状态(提交,接受,重新提交,发布或拒绝)的持续信息,并包含Application_ID字段和名为Status_ID的自动索引字段以及状态文本和状态日期字段。

由于我们希望保持应用程序,文章和资金状态更改的运行日志,因此我们不希望用更新的值覆盖application_status中的现有行,而只想显示最新的状态值。由于应用程序最终会有多个状态更改,因此需要对应用程序数据的状态数据的内部联接应用某种限制,以便每个应用程序标识只返回一行。

这里就是我试图在当前引发错误的查询做的一个例子:

-- simplified example 
SELECT 
application_info.*, 
artstatus.Status_ID AS Article_Status_ID, 
artstatus.Application_ID AS Article_Application_ID, 
artstatus.Status_State_Date AS Article_Status_State_Date, 
artstatus.Status_State_Text AS Article_Status_State_Text 
FROM application_info 
LEFT JOIN (
    SELECT 
    Status_ID, 
    Application_ID, 
    Status_State_Text, 
    Status_State_Date, 
    Status_State_InitiatedBy, 
    Status_State_ChangebBy, 
    Status_State_Notes 
    FROM application_status 
    WHERE Status_State_Text LIKE 'Article Status%' 
    AND Application_ID = application_info.Application_ID -- how to pass the current application_info.Application_ID from the ON clause to here? 
    -- and Application_ID = 29 -- this would be an option for specific IDs, but not an option for getting a complete list of application IDs with status 
    -- GROUP BY Application_ID -- reduces the sub query to 1 row (Yeah!) but returns the first row encountered before the ORDER BY comes into play 
    ORDER BY Status_ID DESC 
    -- a GROUP BY after the ORDER BY might resolve the issue if we could do a sort first 
    LIMIT 1 -- only want to get the first (most recent) row, only works correctly if passing an Application_ID 
) AS artstatus 
ON application_info.Application_ID = artstatus.Application_ID 
-- WHERE application_info.Application_ID = 29 -- need to get all IDs with statu values as well as for specific ID requests 
; 

省去了AND Application_ID = application_info.Application_ID而且随着LIMIT导致选择工作的子查询的一部分,但为给定应用程序ID的每个状态返回一行。我尝试过使用MIN/MAX运营商,但注意到它们在工作时会从application_status表中返回不可预测的行。

我也试图做子在选择的加盟ON部分,但不知道如何使这项工作,因为最终的结果总是需要返回Application_ID(既可以Application_IDStatus_ID返回并用?)。

任何提示如何让这个工作,因为我打算?这甚至可以完成?

进一步编辑:下面的工作查询。关键是将联合中的子查询更深入地移动一层,然后只返回一个状态ID。

-- simplified example (now working) 
SELECT 
application_info.*, 
artstatus.Status_ID AS Article_Status_ID, 
artstatus.Application_ID AS Article_Application_ID, 
artstatus.Status_State_Date AS Article_Status_State_Date, 
artstatus.Status_State_Text AS Article_Status_State_Text 
FROM application_info 
LEFT JOIN (
    SELECT 
    Status_ID, 
    Application_ID, 
    Status_State_Text, 
    Status_State_Date, 
    Status_State_InitiatedBy, 
    Status_State_ChangebBy, 
    Status_State_Notes 
    FROM application_status AS artstatus_int 
    WHERE 
    -- sub query moved one level deeper so current join Application_ID can be passed 
    -- order by and limit can now be used 
    Status_ID = (
     SELECT status_ID FROM application_status WHERE Application_ID = artstatus_int.Application_ID 
     AND status_State_Text LIKE 'Article Status%' 
     ORDER BY Status_ID DESC 
     LIMIT 1 
    ) 
    ORDER BY Application_ID, Status_ID DESC 
    -- no need for GROUP BY or LIMIT here because only one row is returned per Application_ID 
) AS artstatus 
ON application_info.Application_ID = artstatus.Application_ID 
-- WHERE application_info.Application_ID = 29 -- works for specific application ID as well 

-- more LEFT JOINS follow 
; 
+0

'LIMIT'适用于行,不适用于组;你不能通过加入来解决这个问题。我相信你想要[每组前n名](http://www.xaprb。com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql /)其中组是Application_ID,顺序是由status_id决定的。 – 2012-08-08 16:30:17

回答

2

在from子句中不能有相关的子查询。

试试这个想法来代替:

select <whatever> 
from (select a.*, 
      (select max(status_id) as maxstatusid 
       from application_status aps 
       where aps.application_id = a.application_id 
      ) as maxstatusid 
     from application 
    ) left outer join 
    application_status aps 
    on aps.status_id = a.maxstatusid 
. . . 

也就是说,把相关子查询的SELECT子句中,以获得最新的状态。然后将其加入状态表以获取其他信息。并且,用其他细节完成查询。

你似乎很擅长你的SQL技能,所以似乎没有必要为你重写整个查询。

+0

谢谢戈登,我想我只是需要一个理智的检查,我正走向一条错误的道路。你的SQL例子一开始并没有什么意义,但我最终明白了你正在努力的方向。 – 2012-08-08 19:07:32

+1

由于某种原因,我认为我今天回答了这个问题三次。突然之间,这个特殊问题似乎在引起共鸣。顺便说一句,如果你使用的不是mysql的数据库,你还有其他的选择。 – 2012-08-08 19:12:51

+0

你知道,在我发布这个问题之后,我注意到更多的只是今天。我怀疑这个问题的原因是,尽管这是一项常见任务,但我怀疑这不是一个容易在Google搜索中描述的概念。太多JOIN示例模糊了正确的结果链接。 至于我正在使用的数据库,我在MySQL中做这个查询。 – 2012-08-08 19:20:55