简体   繁体   中英

get all records from two tables but from second table only the ones that are not in first

I am creating a MUD game.In that I have two quest tables, there is an active_quests and a completed_quests. There are a lot of customised reports that my players can see.

In one such report, after they choose a bunch of quest_ids, I want to show them their scores/status for that quest. The report should be such that I only want to show the score from the active_quests table if it exists in that table, else from completed_quests.

So the query ( in pseudo-code ) I need is something like:

select active_quests.*
from active_quests
where quest_id in (<list_of_quest_ids>)
and player_id = <player_id>

UNION

select completed_quests.*
from completed_quests
where quest_id NOT in (<the_results_we_got_above>)
and quest_id in (<list_of_quests>)
and player_id = <player_id>

But I have no idea how to write this :(

Assuming that your is a subselect like

  select quest_id from you_quest_table where your_col = your_val

you could use somethings like

    select active_quests.*
    from active_quests
    where quest_id in (
      select quest_id from you_quest_table where your_col = your_val
      )
    and player_id = <player_id>

    UNION

    select completed_quests.*
    from completed_quests
    where quest_id NOT in (

    select active_quests.*
    from active_quests
    where quest_id in (
      select quest_id from you_quest_table where your_col = your_val)
    and player_id = <player_id>

    )
    and quest_id in (
       select quest_id from you_quest_table where your_col = your_val
    )
    and player_id = <player_id>

使用左外部联接可保留左表中的所有记录以及右表中的匹配记录。

One method uses not exists :

select aq.*
from active_quests aq
where aq.quest_id in (<list_of_quest_ids>) and
      aq.player_id = <player_id>
union all
select cq.*
from completed_quests
where not exists (select 1
                  from activequests aq
                  where aq.player_id = cq.player_id and
                        aq.quest_id = cq.quest_id
                 )
      cq.quest_id in (<list_of_quests>) and
      cq.player_id = <player_id>;

Notes:

  • Use UNION ALL unless you explicitly want to remove duplicates (there is a performance penalty).
  • In MySQL, you don't need to repeat the first query in the NOT EXISTS (or NOT IN or LEFT JOIN ) logic, if you are using correlation logic. In other databases, CTEs would simplify the whole thing.
  • With proper indexing, this should be fast.

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