做多个子选择的更好方法是什么?

时间:2013-06-11 08:21:20

标签: sql join subquery

相当标准的设置,包括产品,类别和产品类别的表格,但我想知道是否有更好/更有效的方法来获得产品的几个顶级类别(我真的不想带它们返回单独的行,因此内连接不可行。)

我目前的SQL是:

 SELECT p.*,
  (SELECT TOP 1 category_name FROM categories c INNER JOIN products_and_categories pc ON pc.category_id = c.category_id WHERE p.product_id = pc.product_id AND category_parent = 100 ORDER BY sort) AS cat_1,
  (SELECT TOP 1 category_name FROM categories c INNER JOIN products_and_categories pc ON pc.category_id = c.category_id WHERE p.product_id = pc.product_id AND category_parent = 200 ORDER BY sort) AS cat_2,
  (SELECT TOP 1 category_name FROM categories c INNER JOIN products_and_categories pc ON pc.category_id = c.category_id WHERE p.product_id = pc.product_id AND category_parent = 500 ORDER BY sort) AS cat_3,
  (SELECT TOP 1 category_name FROM (SELECT TOP 2 c.* FROM categories c INNER JOIN products_and_categories pc ON pc.category_id = c.category_id WHERE p.product_id = pc.product_id AND category_parent = 500  ORDER BY sort) c1 ORDER BY sort DESC) AS cat_4,
  (SELECT TOP 1 category_name FROM categories c INNER JOIN products_and_categories pc ON pc.category_id = c.category_id WHERE p.product_id = pc.product_id AND category_parent = 50 ORDER BY sort) AS cat_5,
  (SELECT TOP 1 category_name FROM (SELECT TOP 2 c.* FROM categories c INNER JOIN products_and_categories pc ON pc.category_id = c.category_id WHERE p.product_id = pc.product_id AND category_parent = 50  ORDER BY sort) c1 ORDER BY sort DESC) AS cat_6
FROM products AS p

我很高兴这样做几列,但是想知道是否还有其他方法可以做到这一点?无论是加入PIVOT牌桌还是其他我没想过的东西,或者我是否应该接受这样做。

还有其他一些限制(可能重要也可能不重要):

  • 某些子查询可能无法带回任何结果
  • 我需要前两个类别的一些行(如上面的代码所示)

1 个答案:

答案 0 :(得分:0)

由于您的相关子查询只有简单的等于条件,您可以将它们移动到连接,然后您可以使用TOP 1对类别进行排序,而不是使用ROW_NUMBER(),而只需为每个类别选择前1 product_ID / Parent_category组合,或者在两个字段的情况下,选择第二个类别。

我认为这对你有用:

WITH ProductCategories AS
(   SELECT  pc.Product_ID,
            c.category_name,
            category_parent,
            RowNum = ROW_NUMBER() OVER(PARTITION BY pc.Product_ID, category_parent ORDER BY Sort)
    FROM    categories c 
            INNER JOIN products_and_categories pc 
                ON pc.category_id = c.category_id   
), MaxProductCategories AS
(   SELECT  Product_ID,
            [Cat_1] = MAX(CASE WHEN RowNum = 1 AND category_parent = 100 THEN category_name END),
            [Cat_2] = MAX(CASE WHEN RowNum = 1 AND category_parent = 200 THEN category_name END),
            [Cat_3] = MAX(CASE WHEN RowNum = 1 AND category_parent = 500 THEN category_name END),
            [Cat_4] = MAX(CASE WHEN RowNum = 2 AND category_parent = 500 THEN category_name END),
            [Cat_5] = MAX(CASE WHEN RowNum = 1 AND category_parent = 50 THEN category_name END),
            [Cat_6] = MAX(CASE WHEN RowNum = 2 AND category_parent = 50 THEN category_name END)
    FROM    ProductCategories
    WHERE   RowNum IN (1, 2)
    AND     category_parent IN (50, 100, 200, 500)
    GROUP BY Product_ID
)
SELECT  p.*,
        mpc.Cat_1,
        mpc.Cat_2,
        mpc.Cat_3,
        mpc.Cat_4,
        mpc.Cat_5,
        mpc.Cat_6
FROM    products p
        LEFT JOIN MaxProductCategories mpc
            ON mpc.Product_ID = p.Product_ID;