如何在选择查询(MySQL)中仅消除连续重复而不是所有重复?

Posted

技术标签:

【中文标题】如何在选择查询(MySQL)中仅消除连续重复而不是所有重复?【英文标题】:How to eliminate only continuous duplicates but not all duplicates in a select query (MySQL)? 【发布时间】:2017-07-25 01:17:34 【问题描述】:

我有一张这样的桌子:

17 年 7 月 1 日     100 2017 年 7 月 2 日     100 2017 年 7 月 3 日     300 2017 年 7 月 4 日     300 2017 年 7 月 5 日 500 2017 年 7 月 6 日     500 2017 年 7 月 7 日 300 2017 年 7 月 8 日     400 17 年 7 月 9 日     100 17 年 7 月 10 日     100

我想要输出的是(按此顺序)通过消除连续重复但不是所有重复: 100 300 500 300 400 100

我不能选择 Distinct,因为它会消除 300、100 的第二个实例。有没有办法在 mysql 中实现这个结果? 谢谢!

【问题讨论】:

【参考方案1】:

你想得到以前的值。如果日期确实没有间隙或重复,请执行以下操作:

select t.*
from t left join
     t tprev
     on t.col1 = date_add(tprev.col1, interval 1 day)
where tprev.col2 is null or tprev.col2 <> t.col2;

编辑:

如果日期不满足这些条件,那么你可以使用变量:

select t.*
from (select t.*,
             (@rn := if(@v = col2, @rn + 1,
                        if(@v := col2, 1, 1)
                       )
             ) as rn
      from t cross join
           (select @v := 0, @rn := 0) params
      order by t.col1
     ) t
where rn = 1;

请注意,MySQL 不保证 SELECT 中表达式的求值顺序。所以变量不应该在一个表达式中赋值,然后在另一个表达式中使用——它们应该在一个表达式中赋值。

【讨论】:

【参考方案2】:

处理此问题的一种方法是使用会话变量来跟踪按日期列排序的值的变化。在下面的查询中,我们跟踪值,按日期排序,并为每组相同的值分配一个行号。然后,只保留每组中的第一个值。请注意,这种方法对任意数量的重复项都是稳健的。只要可以按日期对每条记录进行排序,它对于日期中的空白也很可靠。

SET @rn = 1;
SET @val = NULL;

SELECT t.val
FROM
(
    SELECT
        @rn:=CASE WHEN @val = val THEN @rn+1 ELSE 1 END rn,
        @val:=val AS val,
        dt
    FROM yourTable
    ORDER BY dt
) t
WHERE t.rn = 1
ORDER BY t.dt;

输出:

演示在这里:

Rextester

【讨论】:

【参考方案3】:

您可以利用滞后和领先功能。

select y from (select y , lag(y,1,0) over (order by x) as prev_y from t1) where y <> prev_y;

【讨论】:

MySQL 不支持解析函数;您的查询不会运行。

以上是关于如何在选择查询(MySQL)中仅消除连续重复而不是所有重复?的主要内容,如果未能解决你的问题,请参考以下文章

在MySQL中仅选择偶数/奇数行[重复]

在提取数据库中重复行的查询结果中仅选择较新的记录

MySQL 指定查询中的每一列,而不是使用 SELECT * [重复]

如何获取一个MySql表中存在的记录而不是另一个[重复]

如何消除可能以或不以 www 开头的“重复”URL MySQL 行?

如何使mysql查询从MAX(值)中选择数据而不是值?