python - SQLite:仅返回每个组中的前 2 个结果

标签 python sqlite greatest-n-per-group limit-per-group

查了类似问题的其他解决方案,但是sqlite不支持row_number()rank()函数或者没有例子这涉及连接多个表,按多列对它们进行分组,同时仅返回每个组的前 N ​​个结果。

这是我运行的代码

db = sqlite3.connect('mydb')

cursor = db.cursor()

cursor.execute(
    '''
    CREATE TABLE orders(
        id INTEGER PRIMARY KEY, product_id INTEGER,
        client_id INTEGER
        )
    '''
)

cursor.execute(
    '''
    CREATE TABLE clients(
        id INTEGER PRIMARY KEY, gender TEXT,
        city TEXT
        )
    '''
)

cursor.execute(
    '''
    CREATE TABLE products(
        id INTEGER PRIMARY KEY, category_name TEXT
        )
    '''
)

orders = [
    (9, 6), (3, 10), (8, 6), (4, 8),
    (5, 6), (7, 4), (9, 2), (10, 8),
    (4, 6), (3, 1), (10, 2), (9, 8),
    (9, 7), (4, 9), (7, 10), (2, 7),
    (4, 7), (6, 2), (6, 2), (9, 3),
    (10, 6), (4, 4), (2, 6), (3, 8),
    (9, 2), (1, 9), (3, 9), (9, 4),
    (5, 5), (7, 1), (8, 7), (7, 8),
    (6, 3), (9, 6), (8, 3), (7, 1),
    (10, 5), (7, 10), (8, 1), (7, 9),
    (4, 4), (3, 8), (5, 2), (5, 8),
    (6, 10), (9, 7), (2, 2), (4, 10),
    (5, 10), (3, 9)
]

clients = [
    ('Male', 'NY'),
    ('Female', 'NY'),
    ('Male', 'London'),
    ('Male', 'London'),
    ('Male', 'NY'),
    ('Female', 'NY'),
    ('Female', 'London'),
    ('Male', 'London'),
    ('Male', 'NY'),
    ('Female', 'London')
]

products = [
    ('Kitchen', ),
    ('Sport', ),
    ('Furniture', ),
    ('Furniture', ),
    ('Furniture', ),
    ('Sport', ),
    ('Sport', ),
    ('Kitchen', ),
    ('Kitchen', ),
    ('Kitchen', )
]

cursor.executemany("INSERT INTO orders(product_id, client_id) VALUES(?,?)", orders)
cursor.executemany("INSERT INTO clients(gender, city) VALUES(?,?)", clients)
cursor.executemany("INSERT INTO products(category_name) VALUES(?)", (products))

db.commit()

cursor.execute(
    '''
    SELECT
        category_name,
        city, gender,
        product_id, COUNT(product_id)
    FROM orders
    LEFT JOIN products ON product_id = products.id
    LEFT JOIN clients ON client_id = clients.id
    GROUP BY product_id, category_name, city, gender
    ORDER BY category_name, city, gender, COUNT(product_id) DESC
    '''
)

print('''category_name, city, gender, product_id, COUNT(product_id)''')

all_rows = cursor.fetchall()
for a, b, c, d, e in all_rows:
    print(a, b, c, d, e)

db.close()

现在的问题是如何在单个查询中获得这样的输出?我不需要用红线交叉的行,因为我只需要前 2 行。

enter image description here

最佳答案

这可以通过使用 WITH 将现有查询嵌入到 CTE 中,然后在 WHERE ... IN 子查询中使用它来实现。子查询从 CTE 中选择 LIMIT 2 个与 category_name、city 和 gender 匹配的产品 ID,按产品数量排序。

WITH order_groups AS (
  SELECT
    category_name,
    city, gender,
    product_id,
    COUNT(product_id) AS product_count
  FROM orders OO
  LEFT JOIN products ON product_id = products.id
  LEFT JOIN clients ON client_id = clients.id
  GROUP BY product_id, category_name, city, gender
  ORDER BY category_name, city, gender, COUNT(product_id) DESC
)
SELECT * FROM order_groups OG_outer
WHERE OG_outer.product_id IN (
  SELECT product_id
  FROM order_groups OG_inner
  WHERE 
    OG_outer.category_name = OG_inner.category_name AND
    OG_outer.city = OG_inner.city AND
    OG_outer.gender = OG_inner.gender
  ORDER BY OG_inner.product_count DESC LIMIT 2
)
ORDER BY category_name, city, gender, product_count DESC

这会按要求输出以下行:

Furniture|London|Female|4|2
Furniture|London|Female|3|1
Furniture|London|Male|4|3
Furniture|London|Male|3|2
Furniture|NY|Female|5|2
Furniture|NY|Female|4|1
Furniture|NY|Male|3|3
Furniture|NY|Male|4|1
Kitchen|London|Female|9|2
Kitchen|London|Female|8|1
Kitchen|London|Male|9|3
Kitchen|London|Male|8|1
Kitchen|NY|Female|9|4
Kitchen|NY|Female|10|2
Kitchen|NY|Male|1|1
Kitchen|NY|Male|8|1
Sport|London|Female|7|2
Sport|London|Female|2|1
Sport|London|Male|7|2
Sport|London|Male|6|1
Sport|NY|Female|2|2
Sport|NY|Female|6|2
Sport|NY|Male|7|3

关于python - SQLite:仅返回每个组中的前 2 个结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47603191/

相关文章:

python - Heroku 上 Django 的 SMTP 身份验证错误

python - reshape 错误 tensorflow RNN

Python - 使用 BeautifulSoup 抓取 ESPN 表

python - 将 JSON 数据插入 sqlite - 操作错误 : unrecognized token "{"

mysql - MySQL中如何返回结果列表,WHERE只返回一个

sql - Mysql访问主表里面的右连接子查询

python - 简化日期比较

ios - 使用 SharkORM 从本地包读取 SQLite 数据库

mysql - 从 XML stackexchange 转储中提取问答对

postgresql - PostreSQL8.4如何获取字段并添加到group by中?