2013-07-03 6 views
2

mes lignes ressemble à ceci:Sélectionnez uniquement les lignes modifiées

1 
0 ----> Change! This row is of interest 
1 ----> Change again. 
1 
1 
1 
1 
1 
0 ----> Change. 
1 ----> Change. 

Il peut y avoir un million de zéros avant un nouveau 1 et je ne veux que les changements (les lignes marquées par le changement). Cela m'apporterait un résultat avec environ 10 millions de lignes de moins. Nous supportons SQLServer et PostGresSQL. Il est commandé par une colonne d'horodatage. Un 0 est un indicateur système hors ligne et un système en ligne. Un service signale cette information à intervalles et horodatages.

Des idées? Editer: Il y a beaucoup d'autres colonnes on est une colonne timestamp qui détermine l'ordre. Un 0 est un indicateur système hors ligne et un système en ligne. Un service signale cette information à intervalles et horodatages.

Vive

+2

d'autres colonnes de votre tableau? –

+0

Oui beaucoup, j'ai oublié de le dire désolé. –

+1

alors quelles sont les autres colonnes? Y a-t-il un identifiant unique? Comment savez-vous quand un changement s'est produit (c'est-à-dire comment les données sont-elles commandées)? Nous avons besoin de beaucoup plus d'infos? –

Répondre

2

Si vous avez les ID, et ils sont séquentiels, vous pouvez essayer quelque chose comme:

SELECT table1.* FROM table table1, table table2 
WHERE table1.id = table2.id- 1 
AND table1.value != table2.value 

Il est un peu difficile à dire sans voir le reste de votre structure, mais dans ce qui précède cas, value est la colonne qui contient le 0 ou 1 et id est la clé primaire. Si vous n'avez pas de colonne id ou si elles ne sont pas incrémentielles, vous devrez peut-être spécifier un sélecteur plus complexe ou inclure plus de votre schéma ici.

+0

Je n'ai pas d'ID et je ne peux pas influer sur la conception de la base de données. –

+1

@ KarlKildén Alors, comment commandez-vous les rangées? – Igor

+0

Cette solution a un problème qui mordrait s'il y avait des lacunes dans les identifiants. –

0

nous devons savoir comment trouver la ligne précédente, mais la solution générale serait (je en supposant que vos lignes ont la colonne Date et il est unique)

select * 
from temp as t1 
    outer apply 
    (
     select top 1 * 
     from temp as t2 
     where t2.Date < t1.Date /* or you columns */ 
     order by t2.Date desc /* or you columns */ 
    ) 
where t2.value <> t1.value 

EDIT: Comme je suis travaille habituellement sur SQL Server 2008 R2, j'ai oublié les fonctions LAG et LEAD. Donc, sur la base @depesz réponse pour PostgreSQL, voici la version SQL Server:

with CTE_temp as (
    select 
     *, 
     lag([State]) over (order by [Time]) as State_Previous 
    from temp 
) 
select * 
from CTE_temp 
where State_Previous <> [State] 

SQL FIDDLE EXAMPLE

+0

Eh bien, s'il y a une bonne commande possible, alors il y a de meilleures solutions. mais jusqu'à présent, nous ne connaissons pas un tel ordre. –

+0

si par ordre approprié, vous voulez dire des données séquentielles, que oui, c'est possible –

+0

Non, par bon ordre je veux dire - il existe un moyen de trier les données. Au moment de mon commentaire, la question initiale ne contenait aucune information sur «ordre par colonne». –

3

OK. Donc, sur la base d'un commentaire, nous savons qu'il y a une colonne d'horodatage. Supposons que cela s'appelle "event_when", et que la colonne 0/1 s'appelle "status".

Ainsi, nous pouvons:

with x as (
    select 
     *, 
     lag(status) over (order by event_when) is distinct from status as interesting 
    from table 
) 
select * from x where interesting; 
+0

+ 1 requête intéressante, je suppose que c'est PostgreSQL compatible et non SQL Server? –

+0

Je n'ai aucune idée de SQL Server.Ne l'avez pas, n'a pas de fenêtres, ne peut pas tester. Mais - les fonctions de fenêtre et les CTE ne sont pas magiques, et je suppose que toute base de données respectable devrait les avoir. –

+0

Basé sur la réponse d'Alejandro Colorado, il semble que SQL Server a des fonctions de fenêtre - au moins rank() –

-1

Option 1: Utilisation de MS SQL Server 2008

commande avec l'horodatage, on peut utiliser la fonction rank() et une table temporaire. Une variable CTE et une variable de table peuvent également être utilisées. La performance est une partie difficile, donc je suggère de tester les trois options si cela va se répéter à l'avenir.Je vais vous montrer deux exemples:

  • TABLE TEMPORAIRE (try it in SQLFiddle):

    select rank() OVER (ORDER BY order_timestamp) as 'Rank', status into temp1 from temp 
    
    select t1.status as status, case when t1.status - t2.status = 0 then 'not changed' else 'changed' end as changed 
    from temp1 t1, temp1 t2 
    where t1.Rank = t2.Rank + 1 
    
    drop table temp1 
    
  • CTE (try it in SQLFiddle):

    with CTE_temp as (
        select rank() OVER (ORDER BY order_timestamp) as 'Rank', * 
        from temp 
    ) 
    select t1.status as status, case when t1.status - t2.status = 0 then 'not changed' else 'changed' end as changed 
    from CTE_temp t1, CTE_temp t2 
    where t1.Rank = t2.Rank + 1 
    

Option 2: Utilisation MS SQL SERVER 2012

MS SQL SERVER 2012 a présenté lead et lag (http://blog.sqlauthority.com/2011/11/15/sql-server-introduction-to-lead-and-lag-analytic-functions-introduced-in-sql-server-2012/).

Dans ce cas, l'option # 1 est toujours valide, mais vous pouvez également essayer la solution @ RomanPekar.

MISE À JOUR:

Basé sur @ commentaire de RomanPekar (et la downvote de quelqu'un), je dois dire qu'une table temporaire peut parfaitement faire mieux qu'un CTE et une variable de table, surtout quand un grand ensemble de données devrait. L'optimiseur peut utiliser les statistiques de la table temporaire pour établir son plan de requête, ce qui peut entraîner des gains de performances. De même, en fonction de l'utilisation que l'OP veut donner aux données après (peut-être plus de requêtes), la table temporaire est toujours là, aucune nouvelle requête ne doit être exécutée et les index peuvent être utilisés pour améliorer les performances . BTW, hacking ma réponse et la convertir en une variable CTE ou une table est facile, donc je suggère l'OP pour tester la performance pour les trois cas si c'est une opération qu'il va répéter dans le futur.

+0

pas sûr que c'est une bonne solution pour mettre 10 millions de lignes dans la nouvelle table –

+0

@RomanPekar, je vous donne mon avis dans ma réponse mise à jour. –

Questions connexes