J'utilise SQL Server 2016 et les données que je consomme se présentent sous la forme suivante.
CREATE TABLE #tab (cat CHAR(1), t CHAR(2), val1 INT, val2 CHAR(1));
INSERT INTO #tab VALUES
('A','Q1',2,NULL),('A','Q2',NULL,'P'),('A','Q3',1,NULL),('A','Q3',NULL,NULL),
('B','Q1',5,NULL),('B','Q2',NULL,'P'),('B','Q3',NULL,'C'),('B','Q3',10,NULL);
SELECT *
FROM #tab;
Je voudrais obtenir les dernières valeurs non nulles sur les colonnes val1
et val2
regroupées par cat
et triées par t
. Le résultat que je recherche est
cat val1 val2 A 1 P B 10 C
Le plus proche que je suis venu utilise LAST_VALUE
en ignorant le ORDER BY
qui ne fonctionnera pas car j'ai besoin de la dernière valeur non nulle ordonnée.
SELECT DISTINCT
cat,
LAST_VALUE(val1) OVER(PARTITION BY cat ORDER BY (SELECT NULL) ) AS val1,
LAST_VALUE(val2) OVER(PARTITION BY cat ORDER BY (SELECT NULL) ) AS val2
FROM #tab
cat val1 val2 A NULL NULL B 10 NULL
La table réelle contient plus de colonnes pour cat
( colonnes de date et chaîne) et plus de colonnes val (colonnes de date, chaîne et nombre) pour sélectionner la dernière valeur non nulle.
Toutes les idées pour faire cette sélection.
sql-server
window-functions
Edmund
la source
la source
cat
commandé part
.t
valeurs se répètent. Ce ne sont pas des données bien comportées.PARTITION BY cat ORDER BY t, id
par exemple. Sinon, la même requête (n'importe quelle requête) peut vous donner des résultats différents sur des exécutions distinctes. Si les colonnes du tableau ne sont que celles que vous affichez, je ne vois pas comment nous pouvons avoir un ordre déterminé cependant!Réponses:
L'utilisation de la technique de concaténation de The Last non NULL Puzzle par Itzik Ben Gan ressemblerait à ceci avec vos exemples de types de données de table et de colonne.
Une autre façon d'écrire cette requête qui divise les étapes en CTE pour peut-être mieux montrer ce qui se passe. Il donne exactement le même plan d'exécution que la requête ci-dessus.
Cette solution utilise le fait que la concaténation d'une valeur nulle avec quelque chose entraîne une valeur nulle. SET CONCAT_NULL_YIELDS_NULL (Transact-SQL)
la source
Il suffit d'ajouter une vérification pour NULL dans la partition fera l'affaire
la source
Cela devrait le faire. row_number () et une jointure
Si vous n'avez pas un bon tri, vous devez espérer qu'un seul des Q3 n'est pas nul.
la source