2008-09-22 6 views
0

J'ai un problème de base de données que je ne peux actuellement pas contourner avec une solution facile. Dans ma base de données j'ai une table qui stocke les valeurs d'événements .. 0 et 1 avec un horodatage. Le problème étant qu'il est possible que le même événement se produise deux fois en tant que règle métier. Comme ci-dessousFiltrage des valeurs en double au moment de l'exécution dans une base de données sql - set based

  • '22/09/2008 16: 28: 14,133', 0
  • '22/09/2008 16: 28: 35,233', 1
  • « 22/09/2008 16: 29: 16,353' , 1
  • '22/09/2008 16: 31: 37,273', 0
  • '22/09/2008 16: 35: 43,134', 0
  • « 22/09/2008 16 : 36: 39.633 ', 1
  • ' 2008-09-22 16: 41: 40.733 ', 0

dans la vie réelle ces événements sont cyclés et j'essaie d'interroger pour obtenir les cycles de ceux-ci mais je dois ignorer les valeurs en double (1,1) la solution actuelle utilise un curseur SQL pour boucler chacun et jeter sur la valeur si le précédent était le même. J'ai envisagé d'utiliser un déclencheur sur l'insert pour nettoyer dans une table post-traitée, mais je ne peux pas imaginer une solution facile pour faire ce jeu basé.

Des idées ou des suggestions?

Merci

+0

Comment savez-vous quelles sont les valeurs en double? Avez-vous une sorte de clé primaire sur la table? RIght maintenant je ne vois pas comment vous diriez quels deux enregistrements sont réalisés l'un à l'autre. – HLGEM

Répondre

0

Il utilise un serveur SQL Common Table Expression, mais il peut être inséré en ligne, avec une table avec des colonnes t dt et cyclestate:

;WITH Firsts AS (
    SELECT t1.dt 
     ,MIN(t2.dt) AS Prevdt 
    FROM t AS t1 
    INNER JOIN t AS t2 
     ON t1.dt < t2.dt 
     AND t2.cyclestate <> t1.cyclestate 
    GROUP BY t1.dt 
) 
SELECT MIN(t1.dt) AS dt_start 
    ,t2.dt AS dt_end 
FROM t AS t1 
INNER JOIN Firsts 
    ON t1.dt = Firsts.dt 
INNER JOIN t AS t2 
    ON t2.dt = Firsts.Prevdt 
    AND t1.cyclestate <> t2.cyclestate 
GROUP BY t2.dt 
    ,t2.cyclestate 
HAVING MIN(t1.cyclestate) = 0 
1

(préface ....... je n'ai fait cela dans l'oracle, mais je suis assez sûr que si le db prend en charge déclenche il est possible)

Avoir un insert avant déclencheur qui sélectionne la ligne avec la valeur d'horodatage max. Si la valeur de cette ligne est la même que celle que vous souhaitez insérer, ignorez-la.

Cela devrait les garder tous dans un état correct.

Maintenant, si vous avez besoin des deux ensembles d'états stockés, le déclencheur peut toujours insérer sur la table tout-inclus, mais faites la recherche et insérez sur la table 'filtrée' seulement quand la valeur change.

0

Juste pour que je comprenne le problème.

Vous avez, si vous commandez l'ensemble de lignes basé sur l'horodatage, parfois dupliquer valeurs se produisant l'une à côté de l'autre, comme la paire de 1 ci-dessus dans le 2ème et 3rt article? et puis vous avez double 0 dans le 4ème et 5ème, c'est ça?

Et vous voulez le dernier de la paire correspondante (ou de la séquence s'il y en a plus de 2)?

Pourquoi devez-vous les supprimer? Je pose la question parce que, à moins qu'ils n'occupent une part importante de la taille de cette table, il pourrait être plus facile de les filtrer comme vous le faites séquentiellement lorsque vous devez les traiter ou les afficher.

Une solution, mais pas très bon, serait de récupérer l'horodatage minimum ci-dessus l'horodatage de la ligne en cours que vous examinez, puis récupérer la valeur de cela, et si elle est la même chose, don ne retourne pas la ligne actuelle.

Voici le SQL pour obtenir tout:

SELECT timestamp, value 
FROM yourtable 

Et voici comment joindre pour obtenir l'horodatage minimum au-dessus de l'actuel:

SELECT T1.timestamp, MIN(T2.timestamp) AS next_timestamp, T1.value 
FROM yourtable T1, yourtable T2 
WHERE T2.timestamp > T1.timestamp 
GROUP BY T1.timestamp, T1.value 

(je crains la requête ci-dessus sera horriblement lent)

Et puis de récupérer la valeur correspondant à cet horodatage minimum

SELECT T3.timestamp, T3.value 
FROM (
    SELECT T1.timestamp, MIN(T2.timestamp) AS next_timestamp, T1.value 
    FROM yourtable T1, yourtable T2 
    WHERE T2.timestamp > T1.timestamp 
    GROUP BY T1.timestamp, T1.value 
) T3, yourtable AS T4 
WHERE T3.next_timestamp = T4.timestamp 
    AND T3.value <> T4.value 

Malheureusement, cela ne produit pas la dernière valeur, car il a besoin d'une valeur suivante pour comparer. Une simple valeur sentinelle factice (vous pouvez l'associer si vous en avez besoin) va gérer cela.

est ici la décharge de la base de données SQLite J'ai testé la requête ci-dessus contre:

BEGIN TRANSACTION; 
CREATE TABLE yourtable (timestamp datetime, value int); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:28:14.133',0); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:28:35.233',1); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:29:16.353',1); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:31:37.273',0); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:35:43.134',0); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:36:39.633',1); 
INSERT INTO "yourtable" VALUES('2008-09-22 16:41:40.733',0); 
INSERT INTO "yourtable" VALUES('2099-12-31 23:59:59.999',2); 
COMMIT; 

Et voici le (formaté) Sortie:

timestamp     value 
2008-09-22 16:28:14.133 0 
2008-09-22 16:29:16.353 1 
2008-09-22 16:35:43.134 0 
2008-09-22 16:36:39.633 1 
2008-09-22 16:41:40.733 0 
0

Ce problème est vraiment un problème de saisie des données. Un moteur de base de données typique n'est pas un bon choix pour le résoudre. Un simple préprocesseur doit détecter le changement dans le jeu de données d'entrée et ne stocker que les données pertinentes (horodatage, etc.). Une solution facile est dans un environnement de base de données (par exemple dans Oracle) pour créer un paquet qui peut avoir des variables de mémoire locales pour stocker le dernier ensemble de données d'entrée et éliminer l'accès aux bases de données inutiles.

Bien sûr, vous pouvez utiliser toute la puissance de l'environnement de base de données pour définir la «modification du jeu de données d'entrée» et stocker les données filtrées. Donc, cela pourrait être facile ou complexe comme vous le souhaitez.

Questions connexes