SQL:在许多表的同一列中查找重叠的单元格值

时间:2016-12-28 12:38:41

标签: postgresql

我正在使用postgresql,而且我一般都是SQL的新手。

我尝试编写一个查询,检查主列表和多个表之间的值是否重叠。所讨论的值是用户名,并且多个表(总共30个)表示不同游戏的事件数据。

每个游戏都有自己的表格,列表标题相同。 30个具有相同列的表格......:

表名:game1 ... game30

   USERNAME                                 EVENT_TIMESTAMP       OTHER_FELIDS
   2592761928AF756E45891527ED49A7A9         2016-02-01 02:38:05   ...
   79460FE440ADB429F542D2F08A763D50         2016-02-01 02:38:35   ...
   3945B26DD9F6FD2D49574856ECF9FA7D         2016-02-01 02:44:12   ...
   A597AE2CF6E15497EE7AC2A02CEEB32E         2016-02-01 02:46:57   ...
   65DE308FC39980CCD37DBDE8A432F221         2016-02-01 02:46:57   ...
   ...

我有一个指定的user_id列表,我已经用它来创建一个"密钥表"我试图编写一个查询,告诉我我的密钥表列表中的任何用户是否都显示在游戏的事件数据中。 我的密钥表只有两列,看起来像这样:

表名:username_key

EMAIL          HASHED_EMAIL
asd0@asd.com   79460FE440ADB429F542D2F08A763D50
asd1@asd.com   0C450FAC330D69A315604CDE61C7A65E
asd2@asd.com   F2D7714CBA1048A940231087549F1D95
bob@asd.com    FE793A075E0633441B5EE5535FAAEDD2
asd7@asd.com   47FAFD07C174B81BADD28AD9BE64E26B
...

(注意:游戏表和密钥表中的用户名都是哈希加密的电子邮件,因此名称为" HASHED_EMAILS")

我的查询目前看起来像这样:

create temp table players as select ky.hashed_email from username_key as ky 
    inner join game1 g1 on ky.hashed_email = g1.username 
    inner join game2 g2 on ky.hashed_email = g2.username
    inner join game3 g3 on ky.hashed_email = g3.username
    inner join game4 g4 on ky.hashed_email = g4.username
    ...
    inner join game30 g30 on ky.hashed_email = g30.username

当我尝试运行此查询时,它会挂起很长时间......小时并最终超时。

我希望返回显示在一个或多个游戏事件表中的用户列表,或者返回一个空列表(这会告诉我我的密钥表列表中没有人玩过游戏)。

我的查询是否在正确的轨道上? 有没有更快/更有效的方式来完成这项任务,那么我的方式呢? postgresql专家如何解决这个问题(在许多不同的表中查找特定用户名)?

1 个答案:

答案 0 :(得分:0)

如果您关心的是任何表中的用户,而不是多个表中的用户,则可以使用以下替代方法:

  • INUNION

    SELECT * FROM players WHERE hashed_email IN (
        SELECT username FROM game1
        UNION SELECT username FROM game2
        UNION SELECT username FROM game3
        ...
    )
    
  • INOR

    SELECT * FROM player WHERE hashed_email IN (SELECT username FROM game1)
        OR hashed_email IN (SELECT username FROM game2)
        OR hashed_email IN (SELECT username FROM game3)
        ...
    
  • EXISTS

    SELECT * FROM player WHERE EXISTS (SELECT 1 FROM game1 WHERE username=hashed_email)
        OR EXISTS (SELECT 1 FROM game2 WHERE username=hashed_email)
        OR EXISTS (SELECT 1 FROM game3 WHERE username=hashed_email)
        ...
    

可能还有其他一些替代方案。您应该使用EXPLAINEXPLAIN ANALYZE来找出效率更高的内容,但如果所有这三项都能产生截然相似的查询计划,我也不会感到惊讶。

请注意,在每个username表格中game*上设置适当的索引当然会有很大帮助。