简体   繁体   中英

MySQL filtering with several inner joins

I'm currently struggling to figure out a solution to a situation I'm in. I'll give you some background on the database structure: Table ' Entities ' has columns Ent_ID (AI, Int), Ent_Type (Enum, 'Locations, Characters, Houses, Armies') and Obj_ID (Int). The Obj_ID matches the ID from the relevant table. For example the ' Locations ' table has columns Obj_ID (AI, Int), Loc_Name (Text) and Loc_Desc (Text).

Characters can be in different locations depending on the date, so I have a ' TimeSensitives ' table to store these kind of things. This table has columns TS_ID (AI, Int), Ent_ID (Int), TS_Start (Float), TS_End (Float) and TS_Content (Text). The Ent_ID is which character is being some information (such as location). The Ent_ID of the location goes into TS_Content .

So, as you might imagine, I have many locations each with different characters there at different dates. My problem is that I want to be to search for a location that either has a name LIKE the search filter or has a character there that has a name LIKE the search filter.

Up until now I have looped through each Entity with type 'Locations' and then for each one I have looped through all characters currently there. This is my code:

SELECT * 
FROM Entities 
INNER JOIN Locations 
ON Entities.Obj_ID=Locations.Obj_ID 
WHERE Entities.Ent_Type='Locations' 
    AND Loc_Name LIKE ?

Then for each one:

SELECT * 
FROM TimeSensatives 
INNER JOIN Entities 
ON TimeSensatives.Ent_ID=Entities.Ent_ID 
INNER JOIN Characters 
ON Entities.Obj_ID=Characters.Obj_ID 
WHERE TS_Type='Location' 
    AND TS_Content=? 
    AND TS_Start<=? 
    AND TS_End>=?

So as you might have seen, this currently only takes the search filter into account when selecting places. I would now like to implement the search filter onto the characters too but it needs to show places that don't necessarily have matching name but do have a character there with a matching name. I hope that makes sense. My current code wont select any locations without a matching name so there's no chance to search for matching character names.

Is there any way to combine this into one sql statement? Or can somebody think of a way to achieve what I'm trying to do?

Any help would be greatly appreciated and if you need any more info then please ask :) Kallum

SELECT
  Entities.*,
  Locations.Loc_Name as Loc_Name
FROM
  Entities
  INNER JOIN Locations ON Entities.Obj_ID=Locations.Obj_ID 
WHERE
  Entities.Ent_Type='Locations' 
  AND Loc_Name LIKE ?

UNION

SELECT
  LocEnt.*,
  Locations.Loc_Name as Loc_Name
FROM 
  TimeSensatives
  INNER JOIN Entities AS CharEnt ON TimeSensatives.Ent_ID=CharEnt.Ent_ID
  INNER JOIN Characters ON Entities.Obj_ID=Characters.Obj_ID
  INNER JOIN Entities AS LocEnt ON TS_Content.Ent_ID=LocEnt.Ent_ID
  INNER JOIN Locations ON LocEnt.Obj_ID=Locations.Obj_ID 
WHERE
  TS_Type='Location' 
  AND TS_Start<=?
  AND TS_End>=?
  AND Char_Name LIKE ?

will give you all needed locations plus their names

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