sqlite相当于row_number()over(partition by ...?

时间:2010-11-02 01:03:51

标签: sql sqlite

我想知道是否可以使用单个sqlite语句执行以下操作:

我的表看起来像这样:

|AnId|UserId|SomeDate|SomeData|
|123 |A     |1/1/2010|aadsljvs|
| 87 |A     |2/9/2010|asda fas|
|193 |A     |2/4/2010|aadsljvs|
|927 |A     |7/3/2010|aadsasdf|
|816 |B     |1/1/2010|aa32973v|
|109 |B     |7/5/2010|aaasfd10|
| 39 |B     |1/3/2010|66699327|
...

每一行都有唯一的ID,用户ID,日期时间值和其他一些数据。

我想删除记录,因此我根据SomeDate保留每个用户的最新10条记录。

在sql server中我会使用这样的东西:

delete d
from data d
inner join (
    select UserId
        ,  AnId
        ,  row_number() over ( partition by UserId order by SomeDate desc ) 
              as RowNum
    from data 
) ranked on d.AnId = ranked.AnId
where ranked.RowNum > 10

有没有办法在sqlite中执行此操作?具有相同SomeDate的多个记录的边缘情况不是特别担心,例如,如果我保留所有那些记录都没事的话。

5 个答案:

答案 0 :(得分:20)

我知道这个问题已经过时了,但是下面的SQLite语句将在一个语句中执行Rory最初要求的操作 - 删除给定UserId的所有记录,这些记录不是该UserId的10个最新记录(基于SomeDate)

DELETE FROM data
WHERE AnId IN (SELECT AnId
               FROM data AS d
               WHERE d.UserId = data.UserId
               ORDER BY SomeDate DESC
               LIMIT -1 OFFSET 10)

答案 1 :(得分:1)

我需要为每个"对象"获取第二行。在一个与"对象"有一对多关系的表中表。

通常在SQL中,这将使用ROW_NUMBER()OVER(PARTITION BY object_id ORDER BY primary_id DESC)来完成

在Sqlite中,我不得不想出这个voodoo子查询来获得相同的结果

SELECT object_id, MAX(_id)
FROM (SELECT object_id, _id
FROM aTable
EXCEPT
SELECT object_id, MAX(_id)
FROM aTable
GROUP BY object_id)
GROUP BY object_id;

注意:_id是aTable的主键,对象表与查询表有1对多的关系

答案 2 :(得分:0)

这可能非常昂贵(可能只在用户插入新记录时才这样做?)但是如何:

for user in users:
  user-records = select * from records where user=user
  if user-records.length > 10:
    delete from records where user=user and date<user-records[10]

(混合使用SQL和伪代码)

答案 3 :(得分:0)

如果你还没有得到答案。 如果它是一个表,那么您不需要任何联接。你可以使用:

Delete From data
where AnId not in (Select AnId
                   from data
                   Order by SomeDate DESC
                   Limit 10)

答案 4 :(得分:0)

从Sqlite 3.25开始,支持窗口功能。 有关详细信息,请参见https://www.sqlite.org/windowfunctions.html