从集合中获取 "category" 前几行
Get top rows by "category" from a collection
我正在使用 Couchbase 和 N1QL。
假设我有 table 种产品。产品具有 categoryId
和 price
以及其他属性:
id
name
categoryId
price
1
product 1
cat1
5
2
product 2
cat2
100
3
product 3
cat1
25
我知道如何获取单个类别中最昂贵的 5 个产品。我会做这样的事情:
SELECT * FROM products
WHERE categoryId = 'cat1'
ORDER BY price DESC
LIMIT 5
但是我如何查询每个类别前 5 个最昂贵的产品?我知道我可以做 WHERE categoryId IN ['cat1', 'cat2']
,但这会导致这些类别中的前 5 名产品,而不是每个类别 。
有 couchbase 或 N1QL 专家可以帮助我吗?
提前致谢!
使用WINDOW 函数
SELECT p1.*, MISSING AS r
FROM (SELECT p.*,
RANK() OVER (PARTITION BY p.categoryId ORDER BY p.price DESC) AS r
FROM products AS p
WHERE p.categoryId IS NOT NULL) AS p1
WHERE p1.r < 6;
Non-Window 函数(UNNEST 应该表现更好)
CREATE INDEX ix1 ON products(categoryId, price DESC);
SELECT p2.*, MISSING AS r
FROM (SELECT p.*,
(SELECT RAW 1+COUNT(1)
FROM products AS p1
WHERE p1.categoryId = p.categoryId AND p1.price > p.price)[0] AS r
FROM products AS p
WHERE p.categoryId IS NOT NULL) AS p2
WHERE p2.r < 6;
OR
SELECT u.*
FROM (SELECT DISTINCT RAW p.categoryId
FROM products AS p
WHERE p.categoryId IS NOT NULL) AS c
UNNEST (SELECT p1.*
FROM products AS p1
WHERE p1.categoryId = c
ORDER BY p1.categoryId, p1.price DESC
LIMIT 5) AS u;
OR
WITH categoryIds AS (SELECT DISTINCT RAW p.categoryId
FROM products AS p
WHERE p.categoryId IS NOT NULL)
SELECT c AS categoryId,
(SELECT p1.*
FROM products AS p1
WHERE p1.categoryId = c
ORDER BY p1.categoryId, p1.price DESC
LIMIT 5) AS top5
FROM categoryIds AS c ;
我正在使用 Couchbase 和 N1QL。
假设我有 table 种产品。产品具有 categoryId
和 price
以及其他属性:
id | name | categoryId | price |
---|---|---|---|
1 | product 1 | cat1 | 5 |
2 | product 2 | cat2 | 100 |
3 | product 3 | cat1 | 25 |
我知道如何获取单个类别中最昂贵的 5 个产品。我会做这样的事情:
SELECT * FROM products
WHERE categoryId = 'cat1'
ORDER BY price DESC
LIMIT 5
但是我如何查询每个类别前 5 个最昂贵的产品?我知道我可以做 WHERE categoryId IN ['cat1', 'cat2']
,但这会导致这些类别中的前 5 名产品,而不是每个类别 。
有 couchbase 或 N1QL 专家可以帮助我吗?
提前致谢!
使用WINDOW 函数
SELECT p1.*, MISSING AS r
FROM (SELECT p.*,
RANK() OVER (PARTITION BY p.categoryId ORDER BY p.price DESC) AS r
FROM products AS p
WHERE p.categoryId IS NOT NULL) AS p1
WHERE p1.r < 6;
Non-Window 函数(UNNEST 应该表现更好)
CREATE INDEX ix1 ON products(categoryId, price DESC);
SELECT p2.*, MISSING AS r
FROM (SELECT p.*,
(SELECT RAW 1+COUNT(1)
FROM products AS p1
WHERE p1.categoryId = p.categoryId AND p1.price > p.price)[0] AS r
FROM products AS p
WHERE p.categoryId IS NOT NULL) AS p2
WHERE p2.r < 6;
OR
SELECT u.*
FROM (SELECT DISTINCT RAW p.categoryId
FROM products AS p
WHERE p.categoryId IS NOT NULL) AS c
UNNEST (SELECT p1.*
FROM products AS p1
WHERE p1.categoryId = c
ORDER BY p1.categoryId, p1.price DESC
LIMIT 5) AS u;
OR
WITH categoryIds AS (SELECT DISTINCT RAW p.categoryId
FROM products AS p
WHERE p.categoryId IS NOT NULL)
SELECT c AS categoryId,
(SELECT p1.*
FROM products AS p1
WHERE p1.categoryId = c
ORDER BY p1.categoryId, p1.price DESC
LIMIT 5) AS top5
FROM categoryIds AS c ;