J'ai une grosse requête qui renvoie des lignes où l'une des colonnes a des valeurs dupliquées, par exemple:
CREATE TABLE #temp (SysId VARCHAR(10), col1 INT);
INSERT INTO #temp VALUES ('A', 1), ('B', 1), ('A', 1);
WITH cte AS (
SELECT * FROM #temp
), sysids AS (
SELECT SysId FROM #temp GROUP BY Sysid HAVING COUNT(*) = 1
)
SELECT * FROM #temp WHERE EXISTS (SELECT SysId FROM sysids);
DROP TABLE #temp;
sysid est la colonne que je veux filtrer par, donc dans l'exemple ci-dessus, je ne veux que la dernière ligne de sortie car A apparaît plus d'une fois. J'ai essayé de le faire pour les filtrer:
| sysid | col1 | col2 | A | 1 | 2 | A | 2 | 3 | B | 1 | 4
Je m'attendais à ce que la sélection finale contienne uniquement la ligne B, dans l'exemple ci-dessus. Cependant, je les reçois toujours tous, et je ne comprends pas pourquoi.
De toute évidence, dans cet exemple spécifique, je n'ai pas besoin de la partie cte mais ma vraie requête est assez complexe avec plusieurs unions.
3 Réponses :
Vous pouvez utiliser une sous-requête agrégée corrélée et NOT EXISTS .
SELECT t1.*
FROM #temp t1
WHERE NOT EXISTS (SELECT ''
FROM #temp t2
WHERE t2.sysid = t1.sysid
HAVING count(*) > 1);
Oh, approche intéressante. J'avais pensé à utiliser un NOT IN. Est-ce que le NON EXISTANT devrait-il être plus performant ou dépend-il du volume?
@Ben: Avec un index sur sysid , je pourrais imaginer que cela soit assez efficace. Au moins, ça vaut le coup d'essayer.
CREATE TABLE #temp (SysId VARCHAR(10), col1 INT);
INSERT INTO #temp VALUES ('A', 1), ('B', 1), ('A', 1);
WITH cte AS (
SELECT * FROM #temp
), sysids AS (
SELECT SysId FROM #temp GROUP BY Sysid HAVING COUNT(SysId) =1
)
SELECT * FROM #temp WHERE SysId IN (SELECT SysId FROM sysids);
DROP TABLE #temp;
Veuillez essayer ceci:
;WITH cte AS (
SELECT t.SysId,t.col1,COUNT(1)OVER(PARTITION BY t.SysID) AS [cnt]
FROM #temp t
)
SELECT c.SysId,c.col1
FROM cte c WHERE c.cnt = 1;
Le problème est que vous ne reliez pas le
existeà la requête externe (commewhere sysids.sysid = # temp.sysid). Tel qu'il est actuellement écrit, au moins unsysidexiste danssysids, donc la clause where est vraie pour chaque ligne. La requête telle qu'elle est écrite n'est pas différente de, disons,où existe (sélectionnez object_id dans sys.objects)car elle n'a aucune relation avec la requête externe.