簡體   English   中英

執行 SQLite SELECT 替換整數和字符串的變量列表?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM