[英]Execute SQLite SELECT substituting both integers and a variable list of strings?
我正在嘗試 select 一系列 10 本書,每本書都由不同的作者撰寫。
所以我得到了一個結果,將其作者添加到 authors_done 列表中,並嘗試獲得另一個:
authors_done = []
for x in range(10):
db_cursor.execute('SELECT title, author FROM books WHERE (year between ? and ?) and (country = ?) and (author not in (?)) ORDER BY RANDOM() LIMIT 1', (min_year, max_year, country, ','.join(authors_done)))
curtitle, curauthor = db_cursor.fetchone()
authors_done.append(curauthor)
我沒有收到任何錯誤,但我收到的是重復作者,而不是 10 個不同的作者。
我有一種感覺,我應該使用 executemany 和 f 字符串,但我不知道如何使它工作。
PS再想一想,獲得一個不同的作者列表是否更有意義,然后遍歷該列表並為每位作者獲得一本隨機書?
你基本上是在要求 10 件事,然后看第一個,扔掉另外 9 個,然后再做一遍,再做 9 次。 你的author not in
檢查中什么都不做,因為它期待一個數組而不是一個字符串。 無論如何,您可以在 SQL 中完成這一切。
SELECT
title, author
FROM books
WHERE
(year BETWEEN ? AND ?)
AND (country = ?)
這將獲得所有(title, author)
對。 如果有超過 10 個東西,你可以添加LIMIT 10
,並且你只想要前 10 個。
然后使用:
title_authors = db_cursor.fetchall()
如果實際上每個作者可能有不止一本書,但您只想獲取每個作者和一個隨機標題,您可以這樣做:
SELECT
title, author
FROM books
WHERE
(year BETWEEN ? AND ?)
AND (country = ?)
GROUP BY author
如果實際上有超過 10 個作者,而您只想要 10 個,則可以在該語句中添加LIMIT 10
。
針對您的評論,我認為這更棘手。 可以在 SQL 中執行,但只能使用子查詢 IIRC。 我相信還有另一個關於它的 SO 帖子,但我找不到它。 鑒於您有 Python 可用,我認為在那里處理它會更容易。
就像是?
import random
from collections import defaultdict
db_cursor.execute("""
SELECT title, author
FROM books
WHERE (year BETWEEN ? AND ?) AND country = ?
""", (min_year, max_year, country))
books = db_cursor.fetchall() # this is all pairs (title, author)
author_books = defaultdict(list) # this will be author => all titles
for title, author in books:
author_books[author].append(title)
selection = [
(random.choice(all_titles), author)
for author, all_titles in author_books.items()
] # back to (title, author) pairs
如果你真的想要純 SQL,那就是
WITH all_titles AS (
SELECT title, author
FROM books
WHERE (year BETWEEN ? AND ?) AND (country = ?)
ORDER BY RANDOM()
) SELECT
title, author
FROM all_titles
GROUP BY author
這是因為您不能在GROUP BY
之前放置ORDER BY
語句,因此您必須跳過箍來執行此操作。
您可以使用ROW_NUMBER()
window function 為每個作者選擇 1 個隨機title
,然后選擇10
隨機author
:
SELECT title, author
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY author ORDER BY RANDOM()) rn
FROM books
WHERE (year BETWEEN ? AND ?) AND (country = ?) AND (author NOT IN (?))
)
WHERE rn = 1
ORDER BY RANDOM() LIMIT 10
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.