根据表中每个组的唯一列选择行

Posted

技术标签:

【中文标题】根据表中每个组的唯一列选择行【英文标题】:select the rows based on unique column of each group from the table 【发布时间】:2020-09-10 19:06:08 【问题描述】: ---------------- c_id s_id p_id (customer_id, service_id, provider_id) ---- ---- ------ 1, 1, 1 - 无法选择,因为下一个条目具有相同的 p_id 1, 2, 1 1、3、3 2, 1, 1 2、2、2 2、3、3 3, 1, 3 - 无法选择,因为下一个条目具有相同的 p_id 3, 2, 3 - 无法选择,因为下一个条目具有相同的 p_id 3、3、3

编写查询以从上述数据产生以下结果的成本效益高的方法是什么?

---------------- c_id s_id p_id ---- ---- ------ 1, 2, 1 1、3、3 2, 1, 1 2、2、2 2、3、3 3、3、3

【问题讨论】:

mysql 5.7.23 @BarbarosÖzhan 无法选择,因为下一个条目具有相同的 p_id 术语“下一个”只有在指定排序顺序后才有意义。同一个 c_id 中的 ORDER BY s_id 是否安全排序? s_id 是否包含从 1 开始的自然数,并且每个单独的 c_id 没有跳过值?是否有可能某些 c_id 具有 p_id 值,例如 1,2,1,1? @Akina 我可以在每一行添加新列 timestamp 以根据时间戳对 p_id 进行排序并选择最新的常用 p_id。 向我们展示一些方法,我们会选择最具成本效益的。 【参考方案1】:

在 MySQL 8.0 中,您可以使用 lead() 检索“下一个”p_id,并使用该信息过滤掉 pid 与下一个值相同的行。

select *
from (
    select t.*, lead(p_id) over(partition by c_id order by s_id) lead_p_id
    from mytable t
) t
where not p_id <=> lead_p_id

在早期版本中,您通常会使用相关子查询:

select t.*
from mytable t
where not pid <=> (
    select p_id
    from mytable t1
    where t1.c_id = t.c_id and t1.s_id > t.s_id
    order by t1.s_id
    limit 1
)

【讨论】:

@Akina:谢谢。我为早期版本添加了解决方案。 假设 p_id 对于某些 c_id 是 1,2,1,1... 第一行将丢失。 @Akina:我不这么认为(如果我理解正确的话)。两个查询始终使用s_id 对具有相同p_id 的行进行排序。 是的,他是对的@Akina。看看this。恭喜 GMB,这是一个很棒的解决方案。【参考方案2】:

我不太确定这是否是最具成本效益的,但它似乎是我能想到的最明显的解决方案。

select 
   c_id
   ,max(s_id) [s_id]
   ,p_id
from
  `table_name`
group by
   c_id
   ,p_id

【讨论】:

【参考方案3】:

如果s_id是一个没有间隙的序列,你可以使用:

select t.*
from t left join
     t tnext
     on tnext.c_id = t.c_id and tnext.s_id = t.sid + 1
where not (tnext.p_id <=> t.p_id);

【讨论】:

以上是关于根据表中每个组的唯一列选择行的主要内容,如果未能解决你的问题,请参考以下文章

从表中选择最新的带时间戳的值,该表对于一个列 id 有多个条目,对于每个唯一的列 id 和来自另一个表的数据

选择所有唯一元组的 SQL 查询

根据 2 个条件选择组的行,但结合该组的唯一类别

HeidiSQL 根据两个条件从两个表中选择列

如何根据多个排序列选择每组的第一行?

根据字段名称列选择