[英]Better way of doing multiple sub-selects?
Pretty standard setup with a table of products, categories and products in categories, but I was wondering if there is a better/more effective way to get the several top categories for a product (I don't really want to bring them back as separate rows so an inner join isn't viable). 使用产品,类别和类别中的产品表的标准设置,但是我想知道是否有更好/更有效的方法来获取产品的几个顶级类别(我真的不希望将它们分开行,因此内部联接不可行)。
The SQL I have currently is: 我目前拥有的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
I'm happy enough doing it this way for a couple of columns, but was wondering if there was any other way to do it? 我很高兴以这种方式在几个专栏文章中这样做,但是想知道是否还有其他方法可以这样做? Either by joining on a PIVOT table or something else I've not thought of or if I should just accept doing it this way.
通过加入PIVOT表或其他我没有想到的东西,或者我是否应该接受这种方式。
There are a couple of other restrictions (which may or may not be important): 还有其他一些限制(可能不重要):
Since your correlated subqueries only have simple equals conditions you can move these to a join, then rather than using TOP 1
you can use ROW_NUMBER()
to sort your categories, then only select the top 1 for each product_ID/Parent_category combination, or in the case of two of your fields, select the the second category. 由于您的相关子查询只有简单的等式条件,因此可以将其移至联接,然后可以使用
ROW_NUMBER()
而不是使用TOP 1
来对类别进行排序,然后仅为每个product_ID / Parent_category组合选择前1个,或者在如果您有两个字段,请选择第二个类别。
I think this would work for you: 我认为这对您有用:
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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.