简体   繁体   中英

Better way to do this query

I have this schema:

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)

I want to know in which Chapter a specific paragraph is. I have the story id and the paragraph id. This is what I tried so far and it gives this correct result:

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 ) 

Your query should not return the correct answer. Unless your data are luckily arranged.

This is because since a Story is split in several Chapters, then your query will always return the first Chapter of the Story, not the first Chapter of the Paragraph.

Example with data:

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|

If you ask your query for (Parag=3, Story=1), then it will return Chapt=1 while the correct answer is 2.

They are other mistakes in your query.

Defining the Chapter range with only the starting paragraph and the ending paragraph means that betweens those bounds, all paragraphs id are in the same Chapter.

Thus, if Paragraph._id is actually a primary key (as your schema let us guess it), then your query can simply be:

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

But if the primary key is in fact {Paragraph._id + Paragraph.story_id} (as your Chapter table may mean it), then it also mean that story_id are ordered in the same Chapter too.

Thus, story_id and paragraph_id are both ordering the paragraphs as if they were an integer part and a decimal part of a sorting value. And the query should be:

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) ))

I'm afraid the complication of the query comes from the complication of the data arrangement. It could be better if the Chapter id was in the Paragraph table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM