【问题标题】:SQL join with condition of last item of the right table右表最后一项条件的 SQL 连接
【发布时间】:2018-06-03 20:05:22
【问题描述】:

对不起,如果标题不是很容易理解,我什至很难表达它!

为简化起见,我在 SQL Server 2012 数据库中有两个表:一个包含请求,另一个包含与这些请求相关的操作(来自服务管理器软件)

Table REQUESTS            Table ACTIONS
+------+-------+---+      +---------+------+--------+
|Req_ID|RFC_Num|...|      |Action_ID|Req_ID|Group_ID|
+------+-------+---+      +---------+------+--------+
| 1    | I01   |...|      |  a      | 1    | 10     |
| 2    | I02   |...|      |  b      | 1    | 20     |
| 3    | I03   |...|      |  c      | 1    | 38     |
| 4    | I04   |...|      |  d      | 1    | 38     |
+------+-------+---+      |  e      | 2    | 10     |
                          |  f      | 2    | 38     |
                          |  g      | 2    | 20     |
                          |  h      | 3    | 38     |
                          |  i      | 4    | 10     |
                          +---------+------+--------+

我希望能够选择该请求的最后一个操作的 group_id = 38 的所有请求,因此它应该返回 req_id 为 1 和 3 的请求,但不是 req2,因为最后一个操作是由另一个组而不是 38也不涉及第 38 组的 req4。

我尝试过类似的东西

select *
from REQUEST r
inner join ACTION a 
    on (
        (r.REQUEST_ID = a.REQUEST_ID) 
        and (select group_id 
            from ACTION a2 
            where a2.action_id = a.action_id
            ).GROUP_ID = 38
        )

但我不知道如何放置“max(action_id)”(或按 desc 顺序选择前 1 个),而且我真的不明白如何使用诸如 have 之类的东西。

我也尝试过这样的请求:

select *
from REQUEST r
inner join ACTION a 
    on (
        (r.REQUEST_ID = a.REQUEST_ID) 
        and (select top 1 a2.action_id, a2.group_id 
            from ACTION a2 
            where a2.action_id = a.action_id
            group by a2.ACTION_ID
            order by a2.action_id desc
            ).GROUP_ID = 38
        ) 

但是我得到了这两个错误:

消息 8120,第 16 级,状态 1,第 6 行
列 ACTION.GROUP_ID 在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中。

消息 116,第 16 级,状态 1,第 11 行
当 EXISTS 不引入子查询时,选择列表中只能指定一个表达式。

感谢您的帮助!

【问题讨论】:

    标签: sql sql-server join


    【解决方案1】:

    您的查询看起来比实际需要的要长。试试这个:

    SELECT *
    FROM requests r
    WHERE (
        SELECT TOP 1 Group_ID
        FROM actions
        WHERE Req_ID = r.Req_ID
        ORDER BY Action_ID DESC
    ) = 38
    

    SQL Fiddle

    【讨论】:

    • 谢谢,很简单,但它做到了!
    【解决方案2】:

    您的连接栏有误,您正在使用:

    (r.REQUEST_ID = a.ACTION_ID) 
    

    但应该是:

    (r.REQUEST_ID = a.REQUEST_ID) 
    

    【讨论】:

    • 是的,你是对的,我将编辑我的第一条消息,但即使这样我也无法弄清楚 :)
    【解决方案3】:

    您可以加入表格,只保留记录WHERE Group_ID = 38,并且对于此请求不存在其他操作,更大的Action_ID

    SELECT r.*
           FROM REQUESTS r
                INNER JOIN ACTIONS a
                           ON a.Req_ID = r.Req_ID
           WHERE a.Group_ID = 38
                 AND NOT EXISTS (SELECT *
                                        FROM ACTIONS ai
                                        WHERE ai.Req_ID = a.Req_ID
                                              AND ai.Action_ID > a.Action_ID);
    

    SQL Fiddle

    【讨论】:

      【解决方案4】:

      我倾向于使用apply:

      select r.*, a.*
      from request r cross apply
           (select top 1 a.*
            from action a
            where a.request_id = a.request_id
            order by a.action_id desc
           )
      where a.group_id = 38;
      

      这假定“最后操作”基于action_id 列。无论定义是什么,order by 使用什么。

      【讨论】:

        猜你喜欢
        • 2013-12-03
        • 1970-01-01
        • 1970-01-01
        • 2020-07-26
        • 2011-04-29
        • 2016-12-22
        • 2015-10-28
        • 2013-09-13
        • 2013-08-13
        相关资源
        最近更新 更多