SQL-соединение с условием последнего элемента правой таблицы - PullRequest
0 голосов
/ 03 июня 2018

Извините, если заголовок не совсем понятен, у меня проблемы даже с его выражением!

Для упрощения у меня есть две таблицы в базе данных 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, и req4, поскольку группа 38 не участвует.

Я пробовал что-то вроде

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)" (или выбрать top 1 с порядком по desc), и я не очень понимаю, как использовать такие вещи, как наличие.

Я также пробовал запросы, каквот это:

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.

Спасибо за помощь!

Ответы [ 4 ]

0 голосов
/ 04 июня 2018

Я был бы склонен использовать 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 использует.

0 голосов
/ 03 июня 2018

Ваш запрос выглядит длиннее, чем нужно.Попробуйте это:

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

0 голосов
/ 03 июня 2018

Вы можете присоединиться к таблицам, сохраняя только записи 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

0 голосов
/ 03 июня 2018

Ваш столбец соединения неправильный, вы используете:

(r.REQUEST_ID = a.ACTION_ID) 

, но должно быть:

(r.REQUEST_ID = a.REQUEST_ID) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...