【问题标题】:SQL select with inner join, sub select and limit带有内连接、子选择和限制的 SQL 选择
【发布时间】:2012-08-08 16:23:29
【问题描述】:

我已经处理这个 SQL 问题大约 2 天了,我怀疑我非常接近解决这个问题,但似乎无法找到完全有效的解决方案。

我正在尝试对两个名为 application_infoapplication_status 的表进行选择性连接,这些表用于存储有关开放获取期刊文章资助请求的信息。

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

因为我们想要保留应用程序、文章和资金状态更改的运行日志,我们不想用更新的值覆盖application_status 中的现有行,而是只想显示最新的状态值。因为应用程序最终将有多个状态更改,所以需要对应用程序数据的状态数据的内部连接应用某种限制,以便每个应用程序 ID 只返回一行。

这是我在当前引发错误的查询中尝试执行的操作的示例:

-- 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(两者都可以@987654338 @ 和 Status_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
;

【问题讨论】:

  • LIMIT 适用于行,而不是组;你不能通过加入自己来解决这个问题。我相信你想要top n per group,其中 group 是 ApplicationID,order 是 status_id。

标签: mysql sql left-join limit subquery


【解决方案1】:

在 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 技能,因此似乎没有必要为您重写整个查询。

【讨论】:

  • 谢谢 Gordon,我想我只是需要一个健全的检查来确定我走错了路。您的 SQL 示例一开始并没有多大意义,但我最终理解了您要表达的意思。
  • 不知什么原因,我想我今天已经回答了三遍了。突然之间,这个特殊的问题似乎引起了共鸣。顺便说一句,如果您使用的是 mysql 以外的数据库,您还有其他选择。
  • 你知道,在我发布这个问题后,我今天才注意到更多。我怀疑这些问题的原因是,虽然这是一项常见任务,但我怀疑这不是一个在 Google 搜索中描述的简单概念。太多的 JOIN 示例模糊了正确的结果链接。至于我使用的数据库,我在 MySQL 中做这个查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
相关资源
最近更新 更多