我有以下查询,它选择每个类别的前3个记录。目前它将记录限制为9.但是,这不正确,因为如果我将数字限制为8,则最后一个子类别会从显示中丢失一条记录。
我想限制每个SubCategories查询号码的记录,即仅限3个子类别的前3个产品。
我所拥有的是以下内容:
SELECT TOP 9 *
FROM tProduct p
WHERE p.ProductID IN (
SELECT TOP 3 ProductID
FROM tProduct PP
WHERE pp.SubCategoryID = p.SubCategoryID
)
ORDER BY SubCategoryID
任何想法如何修改上述内容?
编辑:根据建议CROSS APPLY
,我到目前为止最接近的是:
SELECT * FROM tSubCategory c
CROSS APPLY
(
SELECT TOP(3) *
FROM tProduct p
WHERE
c.SubCategoryID = p.SubCategoryID
ORDER BY
p.ProductID DESC
) x
WHERE c.SubCategoryID BETWEEN 1 AND 2;
但是,查询应仅指定一个数字,即4个类别,而不是1到2之间的数据,这些数字适用于子类别ID。
答案 0 :(得分:1)
这看起来就像Rob Farley在这里提到的CROSS APPLY的一个例子: http://blogs.lobsterpot.com.au/2011/04/13/the-power-of-t-sqls-apply-operator/
对于此特定查询,您需要选择前3个子类别行,然后使用OUTER APPLY将其附加到每个产品行。然而,您将无法在选择中使用前9,因为这将仅占用9行(而不是前9个产品ID)。这需要使用WHERE子句来完成。下面的查询(带有一些列名修改)应该可以解决问题:
SELECT *
FROM Product AS p
OUTER APPLY (
SELECT TOP (3) s.description
FROM SubCategory AS s
WHERE s.ID = p.subcategoryId
GROUP BY s.id, s.description
ORDER BY s.id DESC) as s
WHERE p.Id IN (select distinct top 9 Id from Product);
答案 1 :(得分:1)
你的意思是:
SELECT * FROM
(SELECT TOP(3) * FROM tSubCategory) c
CROSS APPLY
(
SELECT TOP(3) *
FROM tProduct p
WHERE c.SubCategoryID = p.SubCategoryID
ORDER BY p.ProductID DESC
) x;
...我所基于的只是将你的tSubCategory包装到一个子查询中,将它限制为只有三行。
答案 2 :(得分:0)
使用窗口功能。我不确定你想要什么输出,但以下内容应该非常接近:
SELECT p.*
FROM (SELECT p.*,
row_number() over (partition by ProductId order by SubCategoryId) as sc_seqnum,
dense_rank() over (order by ProductId) as p_seqnum
FROM tProduct p
) p
WHERE sc_seqnum <= 3 and -- number of subcategories per product
p_seqnum <= 3 -- number of products to show
答案 3 :(得分:0)
如果我理解正确,这是使用CROSS APPLY
的完美案例。
在这里阅读更多:
http://www.codeproject.com/Articles/607246/Making-OUTER-and-CROSS-APPLY-work-for-you
请看第一个用例。