更好的方法来执行此查询

时间:2012-07-21 00:43:26

标签: mysql sql oracle sqlite

我有这个架构:

Story
_id 
name

Paragraph
_id
text 
story_id

( the chapter can start from a specific story and 
a specific paragraph and
ends with a specific story and specific paragraph).

Chapter
_id
name 
start_story_id
start_paragraph_id( first paragraph id in the story which _id == start_story_id) 
end_story_id
end_paragraph_id ( last paragraph id in the story which  _id == end_story_id)

我想知道具体段落在哪一章。我有故事ID和段落ID。 这是我到目前为止所尝试的,它给出了正确的结果:

SELECT MIN(_id) 
FROM   chapter 
WHERE  ( start_story_id = @param_story_id 
         AND start_paragraph_id >= @param_parahgraph_id ) 
        OR ( end_story_id = @param_story_id 
             AND end_paragraph_id >= @param_parahgraph_id ) 
        OR ( @param_story_id >= start_story_id 
             AND @param_story_id <= end_story_id ) 

1 个答案:

答案 0 :(得分:1)

您的查询不应返回正确的答案。除非您的数据幸运安排。

这是因为一个故事被分成几个章节,那么你的查询将总是返回故事的第一章,而不是段落的第一章。

数据示例:

Story: |1 1 1|2 2 2|3 3 3|
Parag: |1|2|3|4|5|6|7|8|9|
Chapt: |1 1|2 2|3|4 4|5 5|

如果您询问查询(Parag = 3,Story = 1),则返回Chapt = 1,而正确答案为2。

他们是您查询中的其他错误。

仅使用起始段落和结束段落定义章节范围意味着在这些边界之间,所有段落id都在同一章节中。

因此,如果Paragraph._id实际上是主键(因为您的架构让我们猜测它),那么您的查询可以只是:

SELECT _id
FROM chapter
WHERE (start_paragraph_id<=@param_paragraph_id)
AND (@param_paragraph_id<=end_paragraph_id)

但是如果主键实际上是{Paragraph._id + Paragraph.story_id}(因为你的章节表可能意味着它),那么它也意味着story_id也在同一章中排序。

因此,story_idparagraph_id都将段落排序为好像它们是排序值的整数部分和小数部分。查询应该是:

SELECT MIN(_id)
FROM chapter
WHERE
 ( (start_story_id<@param_story_id)
   OR
   ( (start_story_id=@param_story_id)
     AND
     (start_parahraph_id<@param_paragraph_id) ))
 AND
 ( (end_story_id>@param_story_id)
   OR
   ( (end_story_id=@param_story_id)
     AND
     (end_parahraph_id>@param_paragraph_id) ))

我担心查询的复杂性来自数据安排的复杂性。如果章节ID在段落表中可能会更好。