#sql #sql-server-2005 #tsql
#sql #sql-server-2005 #tsql
Вопрос:
Я пытаюсь запросить несколько таблиц в нашей базе данных, которые содержат данные о продукте. Это база данных MSSQL 2005. Проблема в том, что он возвращает несколько строк для одного продукта, когда мне нужно, чтобы он создавал только одну строку для каждого продукта. Blow — это запрос и результаты, которые я использую.
SELECT ProductItem.sku, ProductItem.title, ProductItem.short_desc, ProductItem.long_desc, ProductItem.active, ProductItem.product_item_id,
ProductCategory.category_desc, ProductCategoryMap.product_id, ProductCategory.active AS activecat, Product.adwords_label,
ProductItem.item_price, ProductItem.sale_price
FROM Product INNER JOIN
ProductCategoryMap INNER JOIN
ProductCategory ON ProductCategoryMap.product_category_id = ProductCategory.product_category_id ON
Product.product_id = ProductCategoryMap.product_id FULL OUTER JOIN
ProductItem ON Product.product_key = ProductItem.sku
WHERE (ProductItem.active = 1) AND (ProductCategory.active = 1)
Это возвращает следующие результаты:
Я знаю, что проблема возникает из-за того, что продукт находится в нескольких категориях, но на самом деле мне не нужны все категории, в которых он находится, только одна из них. Поэтому в идеале только один продукт для каждой возвращаемой строки
Однако я не могу понять, как заставить мой запрос достичь этого.
Кто-нибудь может мне помочь, пожалуйста?
Комментарии:
1. Если для продукта существует несколько категорий, и вы выбираете category_desc в списке выбора. Какую категорию вы хотите отобразить или вам все равно, какая из них отображается?
2. Для этого проекта мне все равно, какой из них отображается.
3. Мой ответ наиболее похож на KMs
Ответ №1:
На первый взгляд, уберите столбцы категорий и добавьте DISTINCT. Вы запросили «категорию», чтобы получить все категории.
Также:
- где изменяет ваше ПОЛНОЕ ВНЕШНЕЕ соединение на ВНУТРЕННЕЕ
- получить product_id из Product
- столбец activecat в любом случае подразумевается предложением where
Я изменил его для наглядности и добавил агрегат, чтобы получить одну категорию
SELECT
PI.sku, PI.title, PI.short_desc, PI.long_desc,
PI.active, PI.product_item_id,
PI.item_price, PI.sale_price,
MIN(PC.category_desc),
P.product_id,
1 AS activecat, --implied by filter
P.adwords_label
FROM
ProductItem PI
INNER JOIN
Product P ON P.product_key = PI.sku
INNER JOIN
ProductCategoryMap PCM ON P.product_id = PCM.product_id
INNER JOIN
ProductCategory PC ON PCM.product_category_id = PC.product_category_id
WHERE
(PI.active = 1) AND (PC.active = 1)
GROUP BY
PI.sku, PI.title, PI.short_desc, PI.long_desc,
PI.active, PI.product_item_id,
PI.item_price, PI.sale_price,
P.product_id,
P.adwords_label
Редактировать: вы можете привести его в порядок с помощью APPLY, который также будет иметь дело с отсутствием категорий, если изменить его на OUTER APPLY
SELECT
PI.sku, PI.title, PI.short_desc, PI.long_desc,
PI.active, PI.product_item_id,
PI.item_price, PI.sale_price,
PC2.category_desc,
P.product_id,
PC2.active AS activecat,
P.adwords_label
FROM
ProductItem PI
INNER JOIN
Product P ON P.product_key = PI.sku
CROSS APPLY
(
SELECT TOP 1
PC.category_desc, PC.active
FROM
ProductCategoryMap PCM
INNER JOIN
ProductCategory PC ON PCM.product_category_id = PC.product_category_id
WHERE
P.product_id = PCM.product_id AND PC.active = 1
ORDER BY
PC.category_desc
) PC2
WHERE
PI.active = 1
Комментарии:
1. Я понимаю, о чем вы говорите, и я бы так и сделал … НО мне нужно выделить хотя бы одну категорию для этого проекта.
2. Потрясающе, отлично сработало. Я не гуру sql и не разобрался бы в этом без вашей помощи. Спасибо!
Ответ №2:
Ответ немного зависит от того, что вы хотите.
Если вас интересует категория продукта только ради вопроса «есть ли у этого продукта хотя бы 1 активная категория?» Ваш запрос будет выглядеть следующим образом …
SELECT DISTINCT
ProductItem.sku,
ProductItem.title,
ProductItem.short_desc,
ProductItem.long_desc,
ProductItem.active,
ProductItem.product_item_id,
ProductCategoryMap.product_id,
Product.adwords_label,
ProductItem.item_price,
ProductItem.sale_price
FROM
Product
INNER JOIN ProductCategoryMap ON Product.product_id = ProductCategoryMap.product_id
INNER JOIN ProductCategory ON ProductCategoryMap.product_category_id = ProductCategory.product_category_id
FULL JOIN ProductItem ON Product.product_key = ProductItem.sku
WHERE
(ProductItem.active = 1) AND
(ProductCategory.active = 1)
Если вас вообще не волнует категория, это будет выглядеть так ….
SELECT
ProductItem.sku,
ProductItem.title,
ProductItem.short_desc,
ProductItem.long_desc,
ProductItem.active,
ProductItem.product_item_id,
ProductCategoryMap.product_id,
Product.adwords_label,
ProductItem.item_price,
ProductItem.sale_price
FROM
Product
INNER JOIN ProductCategoryMap ON Product.product_id = ProductCategoryMap.product_id
ProductCategory.product_category_id
FULL JOIN ProductItem ON Product.product_key = ProductItem.sku
WHERE
(ProductItem.active = 1)
Если вы хотите включить названия активных категорий в виде списка CSV (просто учитывайте план выполнения, если это большой набор результатов)….
SELECT ProductItem.sku,
ProductItem.title,
ProductItem.short_desc,
ProductItem.long_desc,
ProductItem.active,
ProductItem.product_item_id,
ProductCategory.category_desc,
ProductCategoryMap.product_id,
ProductCategory.active AS activecat,
Product.adwords_label,
ProductItem.item_price,
ProductItem.sale_price,
(SELECT substring((SELECT ( ', ' CAST(PC.category_desc AS varchar(50)))
FROM ProductCategory PC
WHERE PC.product_category_id = ProductCategoryMap.product_category_id AND
PC.active = 1
FOR XML PATH( '' )
), 3, 8000 )
) AS ProductCategoriesCSV
FROM
Product
INNER JOIN ProductCategoryMap ON Product.product_id = ProductCategoryMap.product_id
INNER JOIN ProductCategory ON ProductCategoryMap.product_category_id = ProductCategory.product_category_id
FULL JOIN ProductItem ON Product.product_key = ProductItem.sku
WHERE
(ProductItem.active = 1)
HTH,
-эрик
Ответ №3:
Попробуйте…
SELECT
I.sku,
I.title,
I.short_desc,
I.long_desc,
I.active,
I.product_item_id,
T.category_desc,
P.product_id,
T.active AS activecat,
P.adwords_label,
I.item_price,
I.sale_price
FROM
Product P
CROSS APPLY
(
SELECT TOP 1
C.category_desc,
C.active AS activecat
FROM
ProductCategoryMap CM
INNER JOIN ProductCategory C
ON CM.product_category_id = C.product_category_id
WHERE
P.product_id = CM.product_id
AND
(C.active = 1)
) T
FULL OUTER JOIN ProductItem I
ON P.product_key = I.sku
WHERE
(I.active = 1)