从查询中选择一个结果

时间:2011-04-29 15:41:08

标签: 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)

这将返回以下结果:enter image description here

我知道问题出现是因为产品存在于多个类别中,但实际上我不需要其中的每个类别,只需要其中一个。理想情况下,每行返回一个产品

我无法弄清楚如何让我的查询实现这一点。

有人可以帮帮我吗?

3 个答案:

答案 0 :(得分:2)

乍一看,取出类别列并添加DISTINCT。您已经要求“类别”,因此您可以获得所有类别。

此外:

  • WHERE将您的FULL OUTER JOIN更改为INNER
  • 从产品
  • 获取product_id
  • 无论如何,where子句隐含了activecat列

为了清晰起见,我对其进行了调整,并添加了一个聚合来获得一个类别

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,还可以处理 no 类别

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)

答案取决于你想要什么。

如果您只关心产品类别是为了询问“该产品是否至少有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, -eric

答案 2 :(得分:1)

...试

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)