2010-04-20 7 views
1

Par exemple, j'ai:SQL efficace pour compter un événement dans les dernières lignes de X

create table a (i int); 

On suppose il y a 10k lignes.

Je veux compter 0 dans les 20 dernières lignes.

Quelque chose comme:

select count(*) from (select i from a limit 20) where i = 0; 

Est-ce possible de le rendre plus efficace? Comme une seule instruction SQL ou quelque chose?

PS. DB est SQLite3 si cela importe du tout ...

MISE À JOUR

PPS. Pas besoin de regrouper par quoi que ce soit dans cette instance, supposons que la table qui est littéralement 1 colonne (et probablement le DB interne row_ID ou quelque chose). Je suis juste curieux de savoir si cela est possible de faire sans les sélections imbriquées?

+0

Qu'est-ce qui ne va pas avec les sélections imbriquées? J'aurais tendance à penser que la solution d'OrbMan est la plus rapide et la plus propre possible. –

+0

Absolument rien! :) Comme je l'ai dit, je me demandais s'il y avait une meilleure façon de le faire. Si cela ne peut pas être optimisé, alors ça va. Dans ce cas, il semble que les sélections imbriquées sont la solution la plus rapide et la plus optimale. – rytis

Répondre

1

Si vous ne supprimez pas les lignes de la table, vous pouvez essayer la requête hacky suivante:

SELECT COUNT(*) as cnt 
FROM A 
WHERE 
    ROWID > (SELECT MAX(ROWID)-20 FROM A) 
    AND i=0; 

Il fonctionne avec ROWIDs seulement. Comme le documentation dit: Les rangées sont stockées dans l'ordre de rowid.

2

Vous aurez besoin de commander par quelque chose afin de déterminer les 20 dernières lignes. Quand vous dites dernier, voulez-vous dire par date, par ID, ...?

Quelque chose comme cela devrait fonctionner:

select count(*) 
from (
    select i 
    from a 
    order by j desc 
    limit 20 
) where i = 0; 
+0

bien, 'limite X 'est suffisant dans ce cas, car je n'ai pas besoin de le faire par temps ou quoi que ce soit, donc littéralement comment DB retourne les lignes (ID interne je présume) me convient. – rytis

+3

Si vous ne commandez pas par quelque chose, vous pouvez obtenir des résultats incohérents d'une requête à l'autre, car l'ordre est indéterminé par définition sans clause 'ORDER BY'. – RedFilter

1

Vous devez vous rappeler à l'ordre par lorsque vous utilisez limite, sinon le résultat est indéterminée. Pour obtenir les dernières lignes ajoutées, vous devez inclure une colonne avec la date d'insertion, puis vous pouvez l'utiliser. Sans cette colonne, vous ne pouvez pas garantir que vous obtiendrez les dernières lignes. Pour le rendre efficace, vous devez vous assurer qu'il existe un index sur la colonne que vous commandez, peut-être même un index clusterisé.

1

Je crains que vous avez besoin d'une nichée de sélection pour pouvoir compter et limiter aux lignes de dernière X à un moment, parce que quelque chose comme ça

SELECT count(*) FROM a GROUP BY i HAVING i = 0 

comptera des 0, mais dans tous les enregistrements de la table, car une limite dans cette requête n'aura fondamentalement aucun effet.

Cependant, vous pouvez optimiser faire COUNT(i) car il est plus rapide COUNT un seul champ de 2 ou plus (dans ce cas, votre table aura 2 champs, i et rowid, qui est automatiquement créé par SQLite dans les tableaux PKless)

Questions connexes