SQLite select语句优化建议

SQLite select语句优化建议,sql,sqlite,Sql,Sqlite,我有一个具有以下结构的SQLite表“详细信息”: 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   
---------------------
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 
我的尝试如下所示,但有两个问题:

这三个额外的名称并不一定总是不同的——我似乎不能排除以前选择的名称,因为变量b/c/d不在其自身合并函数之外的范围内。 由于每个嵌套的select都使用随机函数,因此效率不高。 有人能推荐另一种使用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

做一个完整的外部联接x3,然后简单地随机选择一个名称不相等的行如何?

通过嵌套查询,将名称作为返回值,也可以实现您想要的结果。基本上先得到第四个值,然后是第三个值,依此类推。始终确保它们不匹配。我应该通过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之外,我看不到解决随机函数及其生成的缓慢性的方法,但这还有其他问题。

优化order by 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

我和纽里诺在一起。您没有说明为什么需要将随机选择的四个名称放在一行中,以及为什么必须在后端执行此操作


如果您关心性能,请在客户端范围>=minpkcol和多语句解决方案中生成随机整数,该解决方案使用临时表:

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;

我看不出在sql中进行这种洗牌比在处理数据的代码(如果有)中有什么好处course@neurino:如果在SQL中执行此操作,可能会有一些好处,与从整个列表中选择客户端的项目相比,向客户端传输的数据要少。@neurino:我在iPhone应用程序中使用此代码。因此,我的想法是尽量将传输的数据量和对SQLite db的调用次数保持在最低水平。@OMG Ponies,感谢您的编辑-现在已经学会了如何格式化表格。@Andiry:我认为这也是可以合理提高性能的数百万个用户名的顺序?嗨,Tim,我在一个iPhone应用程序中使用SQLite语句,我的思考过程可能不正确???尽量减少db和iPhone应用程序之间传输的数据。你的想法是一个有趣的方法,但我想我在某个地方读到过,苹果的指导方针是尽可能减少对db的呼叫-事后看来,我可能应该提到这是针对问题中的iPhone应用程序。非常感谢你的评论Tim,他们帮了我大忙,让我能够从另一个角度看待这个问题态度我认为我的最终解决方案将来自于你和安德烈的评论,在我考虑了更多之后,我决定接受你的建议。我已将语句拆分为两个单独的数据库调用,第二个调用使用order by Random返回三行,limit 3只包含Name列。现在的表现好多了。谢谢安德烈,看起来这正是我所需要的。当我有机会的时候,也许是周末繁忙的一周,我会尝试一下。