2010-11-02 9 views
19

Mi piacerebbe sapere se è possibile effettuare le seguenti operazioni utilizzando una singola istruzione SQLite:equivalente SQLite di row_number() su (partizione ...

Il mio tavolo sembra qualcosa di simile:

|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| 
... 

Ogni riga ha un ID univoco, un ID utente, un valore datetime, e di alcuni altri dati.

mi piacerebbe eliminare i record in modo continuo gli ultimi 10 record per utente, sulla base di SomeDate.

In sql server userei qualcosa di simile:

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 

C'è un modo per fare questo in SQLite? Il caso limite in cui ci sono diversi record con lo stesso SomeDate non è una preoccupazione particolare, ad es. se tengo tutti quei documenti che andrebbero bene.

risposta

17

lo so questa domanda è vecchia, ma la seguente istruzione SQLite farà ciò che Rory chiedeva in origine in una dichiarazione: elimina tutti i record per un determinato ID utente che non sono i 10 record più recenti per quell'Idea utente (basato su 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) 
0

Questo potrebbe essere proibitivo (forse solo farlo quando un utente inserisce un nuovo record?), Ma come su questo:

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] 

(in un mix di SQL e pseudocodice)

+0

Certo, posso farlo procedurale, ma voglio un modo per farlo in un unico dichiarazione se possibile. Se procedendo in modo procedurale sarebbe anche possibile utilizzare una singola istruzione per utente, e solo per gli utenti con record nella tabella – Rory

+0

Ah, sì; Non ne ho idea allora. Per curiosità, come puoi farlo in una singola dichiarazione per utente? – sbirch

+0

Bene, questa è la domanda! la sintassi nella domanda mostra come farlo in SQL Server. Non so se questo è possibile in sqlite. Sospetto di no. – Rory

0

Se non hai ancora la risposta. Se si tratta di una tabella, non è necessario alcun join. Si può semplicemente utilizzare:

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

mi serviva per andare a prendere la seconda fila per ogni "oggetto" in una tabella con un 1 a molti relazione alla tavola "oggetto".

Di solito in SQL questo sarà fatto utilizzando ROW_NUMBER() OVER (partizione CON ORDINANZA object_id BY primary_id DESC)

In Sqlite ho dovuto venire con questo voodoo sub-query per ottenere lo stesso risultato

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; 

Nota: la _id è la chiave primaria della Atable e la tabella oggetto ha un numero di rapporto da 1 a con la tabella interrogato

Problemi correlati