2010-04-30 4 views
0

J'ai une requête qui fonctionne:mot-clé SQL Distinct dans l'instruction d'affectation

DECLARE @ProductID int 
SET @ProductID = '1234' 

SELECT DISTINCT TOP 12 a.ProductID 
FROM A a 
WHERE a.CategoryID IN (SELECT b.CategoryID FROM B b WHERE b.ProductID = @ProductID) 
AND a.ProductID != @ProductID 

Il retourne une liste de 12 numéros de produits, tous uniques.

Je dois stocker ces résultats dans une variable, séparée par des virgules, car c'est ce dont la procédure stockée par un tiers a besoin. J'ai donc ceci:

DECLARE @ProductID int 
DECLARE @relatedprods varchar(8000) 
SET @ProductID = '1234' 
SET @relatedprods = '' 

SELECT TOP 12 @relatedprods = @relatedprods + CONVERT(VARCHAR(20), a.ProductID) + ', ' 
    FROM A a 
    WHERE a.CategoryID IN (SELECT b.CategoryID FROM B b WHERE B.ProductID = @ProductID) 
    AND a.ProductID != @ProductID 

SELECT @relatedprods 

Maintenant, aucun d'entre eux sont distincts, mais il retourne 12 lignes.

Maintenant, j'ajouter la « distincte » revenir, comme dans la première requête:

DECLARE @ProductID int 
DECLARE @relatedprods varchar(8000) 
SET @ProductID = '1234' 
SET @relatedprods = '' 

SELECT DISTINCT TOP 12 @relatedprods = @relatedprods + CONVERT(VARCHAR(20), a.ProductID) + ', ' 
    FROM A a 
    WHERE a.CategoryID IN (SELECT b.CategoryID FROM B b WHERE B.ProductID = @ProductID) 
    AND a.ProductID != @ProductID 

SELECT @relatedprods 

Un seul produit est retourné dans la liste séparée par des virgules! Est-ce que 'distinct' ne fonctionne pas dans les instructions d'affectation? Qu'ai-je fait de mal? Ou y a-t-il un moyen de contourner cela?

Merci d'avance!

CONCLUSION:

Je ne sais pas ce qui cause ce problème, bien que la conjecture proposée semble logique. Je suis en mesure de résoudre ce problème par la sous-requête, et je l'afficher pour que les autres puissent voir la solution:

DECLARE @ProductID int 
DECLARE @relatedprods varchar(8000) 
SET @ProductID = '1234' 
SET @relatedprods = '' 

SELECT @relatedprods = @relatedprods + CONVERT(VARCHAR(20), c.ProductID) + ',' 
    FROM (SELECT DISTINCT TOP 12 a.ProductID FROM A a WHERE a.CategoryID IN 
     (SELECT b.CategoryID 
     FROM B b 
     WHERE B.ProductID = @ProductID) 
    AND a.ProductID != @ProductID) c 

SET @relatedprods = SUBSTRING(@relatedprods, 0, LEN(@relatedprods)) 
SELECT @relatedprods 
+0

@Brandi - Quelle version de SQL Server? – Thomas

+0

@Thomas - SQL Server 2008 – Brandi

Répondre

1

Obtenez les 12 enregistrements dans une sous-requête:

declare 
    @ProductID int, 
    @relatedprods varchar(8000) 

set @ProductID = '1234' 
set @relatedprods = '' 

select @relatedprods = @relatedprods + cast(ProductID as varchar) + ',' 
from (
    select distinct top 12 a.ProductId 
    from A a 
    inner join B b on b.CategoryID = a.CategoryID 
    where B.ProductID = @ProductID and a.ProductID != @ProductID 
) x 
+0

Une version de cela a fini par fonctionner pour moi, merci! – Brandi

0

Pouvez-vous utiliser une table temporaire?

DECLARE @relatedProdList TABLE (prod VARCHAR(20)) 
INSERT INTO @relatedProdList 
SELECT DISTINCT TOP 12 CONVERT(VARCHAR(20), a.ProductID) 
FROM A a 
WHERE a.CategoryID IN (SELECT b.CategoryID FROM B b WHERE b.ProductID = @ProductID) 
AND a.ProductID != @ProductID 

SELECT @relatedprods = @relatedprods + prod + ', ' 
FROM @relatedProdList 
0

Ceci est juste une conjecture sauvage, mais je pense que la cession faire en SELECT échoue avec DISTINCT car il doit faire une sorte après avoir créé le valeur (s) de colonne pour appliquer la distinction. J'ai observé un comportement similaire lors de l'ajout d'une clause non triviale ORDER BY (par exemple, commande par une expression).

Si vous avez SQL Server 2005 ou supérieur, vous pouvez également utiliser FOR XML PATH à la place.

DECLARE @ProductID int 
DECLARE @relatedprods varchar(8000) 
SET @ProductID = 1234 

SET @relatedprods = (SELECT DISTINCT TOP 12 
    CONVERT(VARCHAR(20), a.ProductID) + ',' 
    FROM A a 
    WHERE a.CategoryID IN (...) 
    AND a.ProductID != @ProductID 
    FOR XML PATH('')) 

-- FOR XML PATH will add an extra comma at the end, so remove it. 
IF LEN(@relatedProds) > 1 
    SET @relatedProds = SUBSTRING(@relatedProds, 1, LEN(@relatedProds) - 1) 

Puisque vous utilisez une sous-requête au lieu de la syntaxe d'affectation de variables, ces limitations ne sont pas applicables.