2012-08-08 121 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