选择其他行中有条件的行

时间:2019-12-25 12:23:55

标签: mysql sql

如果要从我的表中选择最后一个status_Id的行,

ticketStatus_Id  ticket_Id   status_Id
======================================
1                 1            1
2                 1            2 -
3                 1            3 *
4                 2            1
5                 3            1
6                 3            2 - *
7                 4            1
8                 4            2 -
9                 4            3      
10                4            4 *

我只想选择第3、6、10行。对于该ticket_Id,还有另外一行status_Id = 2(第2、6、8行), 换句话说,如何选择具有ticket_Id = 1,3,4的行3,6,10,还有另一行具有这些ticket_Id和status_Id = 2(第2,6,8行)

5 个答案:

答案 0 :(得分:1)

首先,对于每张票证,我们将获得状态最高的行。我们可以通过自我联接来做到这一点。每行与状态次高的行合并。我们选择没有更高状态的行,这些行将是最高的。 Here's a more detailed explanation

  select ts1.*
  from ticket_statuses ts1
  left outer join ticket_statuses ts2
    on  ts1.ticket_Id = ts2.ticket_Id
    and ts1.status_Id < ts2.status_Id
  where ts2.ticketStatus_Id is null

3   1   3
4   2   1
6   3   2
10  4   4
11  5   3

请注意,我添加了11, 5, 3曲线球以确保我们仅选择状态为2且不大于2的票证。

然后,我们可以将其用作CTE(如果不使用MySQL 8,则可以使用子查询),并仅选择状态为2的票证。

with max_statuses as (
  select ts1.*
  from ticket_statuses ts1
  left outer join ticket_statuses ts2
    on  ts1.ticket_Id = ts2.ticket_Id
    and ts1.status_Id < ts2.status_Id
  where ts2.ticketStatus_Id is null
)
select ms.*
from max_statuses ms
join ticket_statuses ts
  on  ms.ticket_id = ts.ticket_id
  and ts.status_id = 2;

3   1   3
6   3   2
10  4   4

这种方法可确保我们选择状态最高的完整行以及它们可能包含的任何其他数据。

dbfiddle

答案 1 :(得分:1)

如果您想要完整的行,那么我将其视为exists

select t.*
from t
where exists (select 1
              from t t2
              where t2.ticket_id = t.ticket_id and t2.status_id = 2
             ) and
      t.status_Id = (select max(t2.status_id)
                      from t t2
                      where t2.ticket_id = t.ticket_id 
                     );

如果只想使用ticket_idstatus_id(而不是整个行),我建议进行聚合:

select ticket_id, max(status_id)
from t
group by ticket_id
having sum(status_id = 2) > 0;

对于您来说,ticketStatus_Id似乎随着status_id的增加而增加,因此您可以使用:

select max(ticketStatus_Id) as ticketStatus_Id, ticket_id, max(status_id) as Status_Id
from t
group by ticket_id
having sum(status_id = 2) > 0;

答案 2 :(得分:1)

这基本上是“每组最后一行”的问题。您将找到一些解决方案here。我更喜欢的解决方案是:

select t.*
from (
  select max(ticketStatus_Id) as ticketStatus_Id
  from mytable
  group by ticket_Id
) tmax
join mytable t using(ticketStatus_Id)

您的问题的不同之处在于,您有一个条件,需要在组内指定特定值。这可以通过子查询中的JOIN来解决:

select t.*
from (
  select max(t1.ticketStatus_Id) as ticketStatus_Id
  from mytable t2
  join mytable t1 using(ticket_Id)
  where t2.status_Id = 2
  group by t2.ticket_Id
) tmax
join mytable t using(ticketStatus_Id)

结果:

| ticketStatus_Id | ticket_Id | status_Id |
| --------------- | --------- | --------- |
| 3               | 1         | 3         |
| 6               | 3         | 2         |
| 10              | 4         | 4         |

View on DB Fiddle

使用窗口函数的解决方案可能是:

select ticketStatus_Id, ticket_Id, status_Id
from (
  select *
  , row_number() over (partition by ticket_Id order by ticketStatus_Id desc) as rn
  , bit_or(status_Id = 2) over (partition by ticket_Id) > 0 as has_status2
  from mytable
) x
where has_status2 and rn = 1

一种相当有表现力的方法是使用EXISTS和NOT EXISTS子查询条件:

select t.*
from mytable t
where exists (
    select *
    from mytable t1
    where t1.ticket_Id = t.ticket_Id
      and t1.status_Id = 2
  )
  and not exists (
    select *
    from mytable t1
    where t1.ticket_Id = t.ticket_Id
      and t1.ticketStatus_Id > t.ticketStatus_Id
  )

答案 3 :(得分:0)

SELECT a.*
FROM t a 
JOIN 
(
  SELECT ticket_id, MAX(status_id) max_status_id 
  FROM t 
  WHERE status_id >= 2 
  GROUP BY ticket_id 
) b 
ON a.ticket_id = b.ticket_id 
  AND a.status_id = b.max_status_id;

答案 4 :(得分:-2)

SELECT
  MAX(m1.ticketstatus_Id) as ticket_status,
  m1.ticket_Id             as ticket,
  MAX(m1.status_Id)        as status
FROM mytable m1
WHERE
  m1.ticket_Id in (select m2.ticket_Id from mytable m2 where m2.ticket_Id=m1.ticket_Id and m2.status_Id=2)
GROUP BY m1.ticket_Id