【问题标题】:Better way to do this query执行此查询的更好方法
【发布时间】:2012-07-20 06:36:42
【问题描述】:

我有这个架构:

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 ) 

【问题讨论】:

  • 你为什么不能只检查(@paragraphid between start_paragraph_id and end_paragraph_id) 的位置?每个新故事都会将段落 ID 重置回 1 吗?
  • 你为什么要在这里>=操作?
  • 此外,章节和故事和段落之间是多对一的关系吗?或一对一(我从你的例子中假设)
  • 一个章节可以跨越多个故事?!?如果 150 是段落 ID,为什么要将其与故事 ID(查询的最后一个子句)进行比较?
  • 令人惊讶...还有为什么你需要start_story_id,因为它可以从start_paragraph_id 推导出来(end_story_id 也一样)

标签: mysql sql oracle sqlite


【解决方案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 在段落表中会更好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多