Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在动态查询的行之间进行选择_Sql_Sqlite_Subquery_Range - Fatal编程技术网

Sql 在动态查询的行之间进行选择

Sql 在动态查询的行之间进行选择,sql,sqlite,subquery,range,Sql,Sqlite,Subquery,Range,假设我有一张书桌: CREATE TABLE book ( -- NOTE: the app guarantees that content is ordered by id id INTEGER PRIMARY KEY, section TEXT NOT NULL, verse INTEGER NOT NULL, content TEXT NOT NULL ); INSERT INTO book (id, section, verse, content

假设我有一张书桌:

CREATE TABLE book (
    -- NOTE: the app guarantees that content is ordered by id
    id INTEGER PRIMARY KEY,
    section TEXT NOT NULL,
    verse INTEGER NOT NULL,
    content TEXT NOT NULL
);

INSERT INTO book (id, section, verse, content) VALUES
    (0, "Prelude", 0, "A long long time ago"),
    (1, "Prelude", 1, "I can still remember"),
    (2, "Chap",    0, "Something happened"),
    (3, "Chap",    1, "Something else happened"),
    (4, "Chap",    2, "A weighty climax"),
    (5, "End",     0, "The end")
;
我希望能够用一个SQL查询在一首诗和一章中查询所有的诗。我可以通过以下SQL实现这一点:

SELECT id, content
FROM book
WHERE
    id BETWEEN
        (SELECT id FROM book WHERE section == "Prelude" AND verse == 1 LIMIT 1)
    AND
        (SELECT id FROM book WHERE section == "Chap" AND verse == 2 LIMIT 1)
这涉及到两个子查询,我不确定这是最好的方法。我是否可以改进此查询,使其不包含子查询,这样子查询越少效率越高?

BETWEEN子句后面的代码将扫描两次表以返回2个ID。但还有另一个问题: 你事先知道哪个id最小,哪个id最高吗? 如果不是,那么您就不能在和之前或之后安全地设置每个返回的ID。 例如,如果您这样做:

id BETWEEN
    (SELECT id FROM book WHERE section == "Chap" AND verse == 2 LIMIT 1)
AND
    (SELECT id FROM book WHERE section == "Prelude" AND verse == 1 LIMIT 1)
一概不退还。 因此,必须将最小id设置为下限,将最大id设置为上限。 使用,以便仅扫描一次表以获取起始ID和结束ID:

WITH cte AS (
  SELECT MIN(id) AS fromId, MAX(id) AS toId FROM book 
  WHERE (section = "Prelude" AND verse = 1) OR (section = "Chap" AND verse = 2)
)
SELECT id, content
FROM book
WHERE id BETWEEN (SELECT fromId FROM cte) AND (SELECT toId FROM cte)
看。 或与CTE交叉连接:

WITH cte AS (
  SELECT MIN(id) AS fromId, MAX(id) AS toId FROM book 
  WHERE (section = "Prelude" AND verse = 1) OR (section = "Chap" AND verse = 2)
)
SELECT b.id, b.content
FROM book AS b CROSS JOIN cte AS c
WHERE b.id BETWEEN c.fromId AND c.toId
看。 结果:

BETWEEN子句后面的代码扫描两次表以返回2个ID。但还有另一个问题: 你事先知道哪个id最小,哪个id最高吗? 如果不是,那么您就不能在和之前或之后安全地设置每个返回的ID。 例如,如果您这样做:

id BETWEEN
    (SELECT id FROM book WHERE section == "Chap" AND verse == 2 LIMIT 1)
AND
    (SELECT id FROM book WHERE section == "Prelude" AND verse == 1 LIMIT 1)
一概不退还。 因此,必须将最小id设置为下限,将最大id设置为上限。 使用,以便仅扫描一次表以获取起始ID和结束ID:

WITH cte AS (
  SELECT MIN(id) AS fromId, MAX(id) AS toId FROM book 
  WHERE (section = "Prelude" AND verse = 1) OR (section = "Chap" AND verse = 2)
)
SELECT id, content
FROM book
WHERE id BETWEEN (SELECT fromId FROM cte) AND (SELECT toId FROM cte)
看。 或与CTE交叉连接:

WITH cte AS (
  SELECT MIN(id) AS fromId, MAX(id) AS toId FROM book 
  WHERE (section = "Prelude" AND verse = 1) OR (section = "Chap" AND verse = 2)
)
SELECT b.id, b.content
FROM book AS b CROSS JOIN cte AS c
WHERE b.id BETWEEN c.fromId AND c.toId
看。 结果:


您的查询很好,尽管它可能不是我将如何编写的。您想要的性能是booksection上的索引,诗句:

有了这样一个索引,我可能会将条件移到FROM子句:


这种形式或您的形式中的每个子查询实际上只是在索引中提取一个值。很快。然后WHERE子句在一个主键上进行过滤,这个主键也很快。

您的查询很好,尽管它可能不是我编写它的方式。您想要的性能是booksection上的索引,诗句:

有了这样一个索引,我可能会将条件移到FROM子句:


这种形式或您的形式中的每个子查询实际上只是在索引中提取一个值。很快。然后WHERE子句在一个主键上进行过滤,这个主键也很快。

。。。只是蘸。。。不过两次。问题是如何避免这种情况。@forpas。不是真的。索引查找非常快。不需要优化它,至少如果你打算使用一个数据库的话就不需要了。不是真的吗?快速索引查找将发生两次。问题是如何避免这种情况。@forpas。祝你好运任何使用数据库并关心性能的人都会对两次索引查找和一次主键扫描感到满意。这肯定比全表扫描好,这就是为什么这个答案侧重于为查询提供适当的索引。任何处理数据库并关心性能的人只需查找一个索引就会更满意,这就是问题所在。。。。只是蘸。。。不过两次。问题是如何避免这种情况。@forpas。不是真的。索引查找非常快。不需要优化它,至少如果你打算使用一个数据库的话就不需要了。不是真的吗?快速索引查找将发生两次。问题是如何避免这种情况。@forpas。祝你好运任何使用数据库并关心性能的人都会对两次索引查找和一次主键扫描感到满意。这肯定比全表扫描要好,这就是为什么这个答案侧重于为查询提供适当的索引。任何使用数据库并关心性能的人只需查找一个索引就会更满意,这就是问题所在。
SELECT b.id, b.content
FROM book b CROSS JOIN
     (SELECT id
      FROM book
      WHERE section = 'Prelude' AND verse = 1 
     ) id1 CROSS JOIN
     (SELECT id
      FROM book
      WHERE section = 'Chap' AND verse = 2 
     ) id2
WHERE b.id BETWEEN id1.id AND id2.id;