213 votes

Seule une expression peut être spécifiée dans la liste de sélection lorsque la sous-requête n'est pas introduite avec EXISTS

Ma requête est la suivante, et contient une sous-requête en son sein :

 select count(distinct dNum)
 from myDB.dbo.AQ
 where A_ID in 
  (SELECT DISTINCT TOP (0.1) PERCENT A_ID, 
            COUNT(DISTINCT dNum) AS ud 
 FROM         myDB.dbo.AQ
 WHERE     M > 1 and B = 0 
 GROUP BY A_ID ORDER BY ud DESC)

L'erreur que je reçois est ...

Uniquement une expression peut être spécifiée dans la liste de sélection lorsque la sous-requête n'est pas introduite avec EXISTS.

Lorsque j'exécute la sous-requête seule, elle retourne correctement, donc je suppose qu'il y a un problème avec la requête principale ?

271voto

Chris Lätta Points 8653

Vous ne pouvez pas retourner deux (ou plusieurs) colonnes dans votre sous-requête pour effectuer la comparaison dans la clause WHERE A_ID IN (sous-requête) - avec quelle colonne est-il censé comparer A_ID? Votre sous-requête doit uniquement retourner la colonne nécessaire pour la comparaison avec la colonne de l'autre côté du IN. Donc la requête doit être de la forme:

SELECT * From ThisTable WHERE ThisColumn IN (SELECT ThatColumn FROM ThatTable)

Vous voulez également ajouter un tri pour pouvoir choisir seulement parmi les premières lignes, mais vous n'avez pas besoin de retourner le COUNT en tant que colonne pour effectuer votre tri; trier dans la clause ORDER est indépendant des colonnes retournées par la requête.

Essayez quelque chose comme ceci:

select count(distinct dNum) 
from myDB.dbo.AQ 
where A_ID in
    (SELECT DISTINCT TOP (0.1) PERCENT A_ID
    FROM myDB.dbo.AQ 
    WHERE M > 1 and B = 0
    GROUP BY A_ID 
    ORDER BY COUNT(DISTINCT dNum) DESC)

97voto

ShoushouLeb Points 81

Vous ne devriez renvoyer qu'une seule colonne et une seule ligne dans la requête where où vous assignez la valeur retournée à une variable. Exemple :

select * from table1 where Date in (select * from Dates) -- Faux
select * from table1 where Date in (select Column1,Column2 from Dates) -- Faux
select * from table1 where Date in (select Column1 from Dates) -- OK

2 votes

Cela ne m'a pas aidé. Me donne la même erreur. Spécifier la colonne au lieu de * m'a aidé.

14voto

Jim Leonardo Points 1673

Il se plaint de

COUNT(DISTINCT dNum) AS ud 

à l'intérieur de la sous-requête. Seule une colonne peut être retournée de la sous-requête à moins que vous ne réalisiez une requête exists. Je ne suis pas sûr de pourquoi vous voulez compter la même colonne deux fois, en apparence cela semble redondant avec ce que vous faites. La sous-requête ici est seulement un filtre, ce n'est pas la même chose qu'une jointure. C'est-à-dire que vous l'utilisez pour restreindre les données, pas pour spécifier quelles colonnes récupérer.

0 votes

Parfois, vous pouvez vous joindre aux résultats de la requête et cela résoudra le problème!

6voto

SVK Points 876

En plus des très bonnes réponses ici, vous pourriez également essayer ceci si vous voulez utiliser votre sous-requête telle quelle.

Approche:

1) Sélectionnez la colonne désirée (seulement 1) de votre sous-requête

2) Utilisez where pour mapper le nom de la colonne

Code:

 SELECT count(distinct dNum)
 FROM myDB.dbo.AQ
 WHERE A_ID in 
   (
    SELECT A_ID 
    FROM (SELECT DISTINCT TOP (0.1) PERCENT A_ID, COUNT(DISTINCT dNum) AS ud 
          FROM         myDB.dbo.AQ
          WHERE     M > 1 and B = 0 
          GROUP BY A_ID ORDER BY ud DESC
         ) a 
   )

5voto

Bruce Bacher Points 65

Juste au cas où cela pourrait aider quelqu'un, voici ce qui a provoqué cette erreur pour moi: J'avais besoin d'une procédure pour retourner du json mais j'avais omis le for json path:

set @jsonout = (SELECT ID, SumLev, Census_GEOID, AreaName, Worksite 
            from CS_GEO G (nolock) 
                join @allids a on g.ID = a.[value] 
            where g.Worksite = @worksite)

Lorsque j'ai essayé d'enregistrer la procédure stockée, une erreur a été lancée. J'ai corrigé cela en ajoutant for json path à la fin du code de la procédure :

set @jsonout = (SELECT ID, SumLev, Census_GEOID, AreaName, Worksite 
            from CS_GEO G (nolock) 
                join @allids a on g.ID = a.[value] 
            where g.Worksite = @worksite for json path)

1 votes

Merci. Cela m'a également aidé à réaliser que les requêtes internes (pour produire des tableaux d'objets dans un plus grand objet JSON) doivent AUSSI être FOR JSON PATH

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X