Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 优化查询,复制具有最早日期的行_Mysql_Sql_Performance_Query Optimization - Fatal编程技术网

Mysql 优化查询,复制具有最早日期的行

Mysql 优化查询,复制具有最早日期的行,mysql,sql,performance,query-optimization,Mysql,Sql,Performance,Query Optimization,我想优化一个查询,但我不知道如何才能做到这一点。以下是我要查询的表: Device table: Id || PushId || created abc aaa 10/10/13 def aaa 10/12/13 efg abb 9/9/12 我想要的查询如下:我想要获得重复的PUSHID,并从表中删除其中最早的条目。这是我到目前为止选择而不是删除的内容,因为我仍处于测试阶段 select m.*

我想优化一个查询,但我不知道如何才能做到这一点。以下是我要查询的表:

Device table:

Id    || PushId  || created

abc        aaa        10/10/13
def        aaa        10/12/13
efg        abb         9/9/12
我想要的查询如下:我想要获得重复的PUSHID,并从表中删除其中最早的条目。这是我到目前为止选择而不是删除的内容,因为我仍处于测试阶段

select m.* from 

(select pushId, created 
from Device 
group by pushId 
having count(*) >1)

 as m inner join Device mm on mm.pushId = m.pushId and mm.created = m.created;
这会正确返回应该删除的内容,但速度非常非常慢。有没有更快的方法?有没有办法在没有临时桌子的情况下做到这一点?i、 用一次扫描


编辑:这是MySQL,我错误地在里面放了一个MS-SQL标记。抱歉伙计们

您可以使用行号:

Select *
From (Select *,
             Row_Number() over(Partition by Pushid order by created) as row
      From YourTable
)z
where z.row = 1

这将提供MySQL中使用@variables的行数。在这里,它为每个PushId定位除最近的2行以外的所有行

SELECT
      PushId
    , Id
    , created
FROM (
      SELECT
               @row_num :=IF(@prev_value = d.PushId,@row_num+1,1)AS RN
             , d.PushId
             , d.Id
             , d.created
             , @prev_value := d.PushId
      FROM tblDevices d
      CROSS JOIN(SELECT @row_num :=1, @prev_value :='') vars
      ORDER BY
               d.PushId
             , d.created DESC
      ) SQ
WHERE RN > 2
;

您可以通过将顺序eg更改为ASC来查找最早的记录,从而更改结果。注意,交叉连接仅用于将2个@vars附加到每一行&因为只有一行,所以它对记录的实际数量没有影响。然后在查询中设置变量。

可能需要进行一些操作才能使其适合您的delete语句,但请使用MIN函数尝试以下操作,以查找具有多个条目的最低日期+id组合。然后从结果中删除日期,仅提供正确的id:

delete from Device where id in (
    select 
         right(min(cast(cast(created as unsigned) as char(5)) + id),3)
    from Device 
    group by pushid
    having count(*) > 1
)

可能使用自联接,其中推送id匹配且创建日期更大:-

SELECT DISTINCT b.Id
FROM table a
INNER JOIN table b
ON a.PushId = b.PushId
AND a.created > b.created

这将生成重复项,因此使用DISTINCT

如果您必须根据您的数据删除许多行,…,最好使用所需的数据创建一个新表并删除旧表。
删除是仅次于“更新”的最昂贵的操作。

ok,考虑到这是MySQL

 delete from Device where (push_id, created) in
 (
   select 
      pushId, 
      min(created) 
   from 
      Device 
   group by pushId 
   having count(*) >1
 )

这是大多数db系统中速度最快的 无需专家组或订单

 delete from Device where (push_id, created) in
  (
   select 
     pushId, 
     created
   from 
     Device a1
   where 
     EXIST (select 1
              from Device a2
               where a1.pushId=a2.pushId
               and a2.created > a1.created
             )
    )

那没用。你介意解释一下你的问题背后的想法吗?行号不是函数。行号是SQL Server函数。SQL Server 2008支持,很抱歉。我不知道你用的是MySQL。对不起,是我的错。抱歉,我没有正确地放置标签。这与下面的操作完全相同,但如果我错了,请纠正我,但我看不出这比我开始使用的更有效。有一个交叉连接和一个变量赋值。不过,为了方便起见,您是否介意解释一下查询是如何工作的,因为我从来没有使用row_num来帮助查询?交叉连接在这里并不重要,因为它不会扩展记录的数量,也不涉及实际的磁盘i/O。最慢的部分是顺序,但这是无法避免的。比较prev_值和设置每行中两个变量的值时,会进行一些计算,但这实际上非常小,只不过是一个简单的case表达式,即efforce terms.discart我前面的评论。你的解决方案是完美的。感谢Mate,我自己尝试过,问题是如果有多个条目,例如:push id:abc,具有许多不同的IDE和不同的创建日期,此查询将只删除一个条目。i、 e.ID PID CreatedYes,…,假设它只会加倍,因为示例指示最早的创建日期。是否只保留1?我将向您展示,在pleaseI添加了新回复的那一刻,如何将源代码放在这一级别的注释中确保在push_id或push_id上有一个很好的索引,如果双倍数较低,则创建该索引,而不使用创建的索引,因为您总是以块的形式获取行,而不是单个的