sqlite эквивалент row_number () over (разделить на ...? - PullRequest
23 голосов
/ 02 ноября 2010

Я хотел бы знать, возможно ли сделать следующее с помощью одного оператора 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|
...

Каждая строка имеет уникальный идентификатор, идентификатор пользователя, значение даты и времени и некоторые другие данные.

Я хотел бы удалить записи, чтобы сохранить последние 10 записей для каждого пользователя на основе SomeDate.

На сервере SQL я бы использовал что-то вроде этого:

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 ]

20 голосов
/ 12 июня 2013

Я знаю, что этот вопрос старый, но следующий оператор SQLite будет делать то, что Рори первоначально запрашивал в одном операторе: удалить все записи для данного UserId, которые не являются 10 самыми последними записями для этого UserId (на основе 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 голос
/ 10 ноября 2017

Мне нужно было выбрать вторую строку для каждого «объекта» в таблице с отношением 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 ко многим с запрашиваемой таблицей

0 голосов
/ 18 сентября 2018

Начиная с Sqlite 3.25 поддерживаются оконные функции.Подробнее см. https://www.sqlite.org/windowfunctions.html.

0 голосов
/ 11 февраля 2016

Если у вас уже нет ответа. Если это один стол, то вам не нужны никакие объединения. Вы можете просто использовать:

Delete From data
where AnId not in (Select AnId
                   from data
                   Order by SomeDate DESC
                   Limit 10)
0 голосов
/ 02 ноября 2010

Это может быть слишком дорого (возможно, делать это только тогда, когда пользователь вставляет новую запись?), Но как насчет этого:

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 и псевдокода)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...