我有一个带有结构的SQLite表'Details':
ID Name Category
---------------------
1 Matt 0
2 Shervin 0
3 Bob 0
4 Lee 0
5 Rick 0
6 Suraya 0
7 Susan 0
8 Adam 0
9 Jon 1
10 Lorna 1
... and so on .......
我想随机选择一行,然后从三个不同的行中选择三个名称(再次最好随机选择)。我想从一个SQLite语句返回所有这些。例如。
ID Name Category Name1 Name2 Name 3
----------------------------------------
3 Bob 0 Matt Lee Susan
我的尝试可以在下面看到,但它有两个问题:
有人可以建议另一种方法来选择我需要的数据(使用SQLite数据库)吗?欢迎提供任何帮助/建议 - 希望我明白我想要达到的目标,随时要求澄清。
我目前的尝试:
SELECT a.Id,
a.Name,
a.Category,
COALESCE((SELECT b.Name
FROM Details b
WHERE b.Id NOT IN (a.Id)
AND b.Category IN (0)
ORDER BY Random()
LIMIT 1),'') as "Name1",
COALESCE((SELECT c.Name
FROM Details c
WHERE c.Id NOT IN (a.Id)
AND c.Category IN (0)
ORDER BY Random()
LIMIT 1),'') as "Name2",
COALESCE((SELECT d.Name
FROM Details d
WHERE d.Id NOT IN (a.Id)
AND d.Category IN (0)
ORDER BY Random()
LIMIT 1),'') as "Name3"
FROM Details a
AND a.Category IN (0)
ORDER BY Random()
LIMIT 1
答案 0 :(得分:3)
我在这里和neurino在一起。你还没有说为什么你需要将随机选择的四个名字放在一行中,为什么必须在后端完成。
如果您担心性能,请在客户端生成随机整数(范围> = min(pkcol)和< = max(pkcol)),直到找到四个不同的行(即实体/名称)。生成的id之一可能没有行存在,但只需几毫秒即可找到。采用随机密钥方法,您可以避免订单。即使对于具有数十亿行的表,该方法也可以快速工作。
P.S。 (在发现它是iPhone应用程序后) 您需要一次调用来获取最小和最大ID值(它是PK,因此使用索引)。然后你至少需要再次调用DB(再次,索引辅助)来使用随机生成的PK值获取四个不同的行[其中ID在(a,b,c,d)中]最大调用次数未知;多少将取决于主键序列的密度。我不认为这将是一个过多的I / O,它将比Random()的订单资源密集程度低得多 - 特别是如果表有很多行。您总是可以随机生成8个,12个,16个ID的ID列表,并且如果返回的值超过4个,则客户端只会剔除所需的4行。
P.P.S。通常情况下,数据库连接的实例化是昂贵的,并且您不希望在循环中执行此操作,或者不希望这样做。但是你可以打开一个连接,运行两个或三个有效的选择,每个选择返回几行,然后关闭,如果你完成了手头的任务。
答案 1 :(得分:1)
多语句解决方案,它使用临时表:
CREATE TEMP TABLE names
AS
SELECT
Id,
Name,
Category
FROM Details
WHERE Category IN (0)
ORDER BY Random()
LIMIT 4;
SELECT
MAX(CASE rowid WHEN 1 THEN Id END) AS Id,
MAX(CASE rowid WHEN 1 THEN Name END) AS Name,
MAX(CASE rowid WHEN 1 THEN Category END) AS Id,
MAX(CASE rowid WHEN 2 THEN Name END) AS Name1,
MAX(CASE rowid WHEN 3 THEN Name END) AS Name2,
MAX(CASE rowid WHEN 4 THEN Name END) AS Name3
FROM names;
DROP TABLE names;
答案 2 :(得分:0)
如何做一个完整的外连接x3,然后简单地选择一个名称不相等的行?
答案 3 :(得分:0)
您还可以通过嵌套查询以将名称作为返回值来实现所需。你基本上先获得第四个值,然后是第三个,依此类推。一直确保它们不匹配。我应该通过Id字段并检查Id的不是冲突而不是名称,但这种方式意味着唯一的名称。
SELECT Id
,Name
,Category
,bName
,cName
,dName
FROM Details,
(
SELECT Name AS bName, cName, dName
FROM Details,
(
SELECT Name AS cName, dName
FROM Details,
(
SELECT Name AS dName
FROM Details
WHERE Category IN (0)
ORDER BY Random()
LIMIT 1
) td
WHERE Name <> dName
AND Category IN (0)
ORDER BY Random()
LIMIT 1
) tc
WHERE Name <> dName
AND Name <> cName
AND Category IN (0)
ORDER BY Random()
LIMIT 1
) tb
WHERE Name <> dName
AND Name <> cName
AND Name <> bName
AND Category IN (0)
ORDER BY Random()
LIMIT 1;
除了在代码中生成随机Id之外,我没有看到Random()函数及其生成的缓慢的方法,但是还有其他问题。
答案 4 :(得分:0)
通过random()语句优化订单有两种主要方法。
第一种方法是完全删除整个表格步骤的排序,但它不适用于所有平台:limit 1 offset random()
,而不是order by random() limit 1
。
另一个适用于所有平台,但要求您的主键密集(一个自动递增的整数,如果有任何删除则没有任何确定它们)。从随机起始点开始预取一小组ID,并在子查询中使用它们:
select *
from (select *
from tbl
where id between :x and :x + 20
)
order by random()
limit 1