Ключевое слово SQL Distinct в операторе присваивания - PullRequest
0 голосов
/ 01 мая 2010

У меня есть запрос, который работает:

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

Возвращает список из 12 номеров продуктов, все уникальные.

Мне нужно сохранить эти результаты в переменной, разделенной запятой, потому что это то, что нужно сторонней хранимой процедуре. Итак, у меня есть это:

 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

Теперь, ни один из них не различим, но он возвращает 12 строк.

Теперь я добавляю «отчетливое» обратно, как в первом запросе:

 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

В списке через запятую возвращается только один товар! Разве «разные» не работает в операторах присваивания? Что я сделал не так? Или есть способ обойти это?

Заранее спасибо!

ВЫВОД:

Я понятия не имею, что вызывает эту проблему, хотя предложенное предположение кажется логичным. Мне удалось решить эту проблему с помощью подзапроса, и я публикую его, чтобы другие могли увидеть решение:

 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

Ответы [ 3 ]

1 голос
/ 01 мая 2010

Получить 12 записей в подзапросе:

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 голосов
/ 01 мая 2010

Это просто дикая догадка, но я ожидаю, что выполнение присваивания в SELECT завершится неудачно с DISTINCT, так как он должен выполнить сортировку после генерации значений столбца, чтобы обеспечить различимость. Я видел похожее поведение при добавлении нетривиального предложения ORDER BY (например, упорядочение по выражению).

Если у вас SQL Server 2005 или выше, вы также можете использовать FOR XML PATH.

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)

Поскольку вы используете подзапрос вместо синтаксиса назначения переменных, эти ограничения не применяются.

0 голосов
/ 01 мая 2010

Не могли бы вы использовать временную таблицу?

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
...