Comment puis-je sélectionner la valeur la plus proche inférieur à et supérieur à une valeur donnée de manière efficace?
J'ai deux tables, une pour les valeurs de l'un pour l'emplacement et suis en train d'interpoler emplacement. Les tables ont été simplifiées à l'suivantes:
CREATE TABLE value(
Timestamp DATETIME2,
Value float NOT NULL,
PRIMARY KEY(Timestamp)
);
CREATE TABLE location(
Timestamp DATETIME2,
Position INT NOT NULL,
PRIMARY KEY(Timestamp)
);
INSERT INTO value VALUES
('2011/12/1 16:55:01', 1),
('2011/12/1 16:55:02', 5),
('2011/12/1 16:55:05', 10),
('2011/12/1 16:55:08', 6);
INSERT INTO location VALUES
('2011/12/1 16:55:00', 0),
('2011/12/1 16:55:05', 10),
('2011/12/1 16:55:10', 5)
Les résultats attendus serait
TimeStamp, Value, LowerTime, LowerLocation, UpperTime, UpperLocation
2011-12-01 16:55:01, 1, 2011-12-01 16:55:00, 0, 2011-12-01 16:55:05, 10
2011-12-01 16:55:02, 5, 2011-12-01 16:55:00, 0, 2011-12-01 16:55:05, 10
2011-12-01 16:55:05, 10, 2011-12-01 16:55:05, 10, 2011-12-01 16:55:05, 10
2011-12-01 16:55:08, 6, 2011-12-01 16:55:05, 10, 2011-12-01 16:55:10, 5
(Gardez à l'esprit que c'est simplifiée des données de l'échantillon pour avoir une idée de la question je suis en train de se produire partout.)
De faire de l'interpolation, j'ai besoin de comprendre le temps et les lieux avant et après les valeurs de temps. Je suis actuellement en train de le faire avec une requête qui ressemble à:
SELECT
V.Timestamp,
V.Value,
(SELECT MAX(Timestamp) FROM dbo.location WHERE Timestamp <= V.Timestamp) as LowerTime,
(SELECT TOP 1 Position FROM dbo.location WHERE Timestamp <= V.Timestamp ORDER BY timestamp DESC) as LowerLocation,
(SELECT MIN(Timestamp) FROM dbo.location WHERE Timestamp >= V.Timestamp) as UpperTime,
(SELECT TOP 1 Position FROM dbo.location WHERE Timestamp >= V.Timestamp ORDER BY timestamp ASC) as UpperLocation
FROM
dbo.value V
Maintenant cela fonctionne, mais, évidemment, est de faire beaucoup de travail. Je pense il doit y avoir une requête de simplification que je suis absente, mais j'ai joué avec elle tous les matins et je n'ai pas trouver quelque chose de concret. En espérant que quelqu'un ici a une meilleure idée.
Je suis actuellement en train d'étudier s'il existe un moyen de comprendre le LowerTime et UpperTime et les utiliser dans la détermination de l'emplacement. Quelque chose comme:
SELECT
V.Timestamp,
V.Value,
(SELECT MAX(Timestamp) FROM dbo.location WHERE Timestamp <= V.Timestamp) as LowerTime,
(SELECT Position FROM dbo.location WHERE Timestamp = LowerTime) as LowerLocation,
(SELECT MIN(Timestamp) FROM dbo.location WHERE Timestamp >= V.Timestamp) as UpperTime,
(SELECT Position FROM dbo.location WHERE Timestamp = UpperTime) as UpperLocation
FROM
dbo.value V
mais cela ne fonctionne pas.
EDIT1: mise à Jour de la requête, comme l'a suggéré. Toutefois, aucun changement visible au moment de l'exécution.
EDIT2: Ajout de mes pensées de l'approche, je suis en train d'essayer.
OriginalL'auteur brianestey | 2012-01-20
Vous devez vous connecter pour publier un commentaire.
Pour plus de simplicité vous pouvez au moins utiliser
MAX()
etMIN()
fonctions d'interrogationtimestamp
champ au lieu deTOP 1
etORDER BY
.Requête complète sera
Merci. J'ai marqué votre réponse comme réponse que c'était la meilleure des options. Ce qui ne l'aider un peu.
OriginalL'auteur Sergey Kudriavtsev
Cela pourrait faire l'affaire (bien que je pense de la jointure semble assez laid):
Malheureusement, comme avec la plupart efficacité/performances des questions, la réponse tend à être essayer un bon nombre de différentes combinaisons avec votre réelle les tables et les données, et de mesurer la façon dont chacun exécute.
Une alternative (en évitant la jointure) à l'aide de la même CTE comme ci-dessus serait:
Le CTE (
OrderedLocations
) est d'essayer de construire un ensemble de lignes où chaque ligne à partir de l'emplacement est adaptée à chaque ligne devalue
. Pour chaque ligne, nous calculons deuxROW_NUMBER
s - le numéro de ligne où nous sommes toutes les lignes ayant une valeur inférieure ou égale timestamp (PrevRN
) dans l'ordre décroissant, et un autre où nous en nombre de toutes les lignes avec une plus grande ou égale timestamp (NextRN
) dans l'ordre croissant. Ensuite, nous construisons notre résultat final en ne considérant que les lignes où l'un de ces numéros de ligne est 1.eh bien, si vous avez des exemples de données et de résultats attendus, veuillez les ajouter à votre question - c'est beaucoup plus facile pour nous d'écrire de travail requêtes, si nous sommes capables de les tester nous-mêmes avant de poster que des réponses.
bonne idée, j'ai mis à jour de nouveau la question avec certains points de données que j'utilise pour les tests et aussi le résultat attendu, je suis à la recherche d'.
Maintenant, j'ai partitionné par
v.Timestamp
dans mon CTE, et obtenir les résultats attendus, vous avez posté. (J'avais d'abord testé avec une seule ligne dans levalue
table, oups)Merci pour la mise à jour. J'ai testé cela et il donne les résultats escomptés, mais je vais avoir quelques problèmes de performances avec ce. Par exemple, j'ai inséré 5000 lignes dans la table de valeurs, 1250 lignes dans l'emplacement de la table et l'original de la requête terminée en 0~1 seconde, mais cette requête ne prend que quelques minutes avec les mêmes données (~5.5 minutes). Est-ce que sembler raisonnable pour vous?
OriginalL'auteur Damien_The_Unbeliever