如何为(m:n关系?)设计表/查询

时间:2013-06-09 18:19:34

标签: sql database-schema

如果m:n这个词不正确,我很抱歉。如果你知道一个更好的术语我会纠正。我有以下情况,这是我原来的数据:

gameID
participID
result

数据本身就是那样

1     5      10
1     4     -10
2     5     150
2     2    -100
2     1     -50

当我提取这个表时,它将很容易地有大约100十亿行和大约1个参与者更多。

我需要:

show me all results of all games from participant x, where participant y was present

幸运的是,只有非常有限的参与者,但这些可能会发生变化,因此我需要一个完整的表格,并且可以在第二步中减少。

我的想法如下,它看起来非常不优化

1)获取包含“观点参与者”的游戏列表“

insert into consolidatedtable (gameid, participid, result)
    select gameID,participID,sum(result) from mastertable where participID=x and result<>0

2)获取包含其他参与者的所有游戏

insert into consolidatedtable (gameid, participid, result)
where gameID in (select gameID from consolidatedtable)
AND participID=y and result<>0

3)从合并表中删除所有游戏,其中count&lt; 2

delete from consolidatedDB where gameID in (select gameid from consolidatedtable where count(distinct(participID)<2 group by gameid)

整件事看起来像是我儿童的解决方案

  1. 我需要每个玩家的合并表
  2. 我将许多游戏插入此表并稍后将其删除
  3. 整个事情需要由参加者参加 整个主表,如果我为几个这样做,它将无法工作 参与者同时
  4. 任何更好的想法,必须是,这些都是如此糟糕。主表将是DW服务器上的postgreSQL,统一视图将是mySQL(但数字运算将在postgreSQL中完成)


    我的问题

    1)我如何构建整合表(s-我需要不止一个),而不必在整个主表上为每个玩家运行单个查询(我需要为玩家x,y,z提供数据)并且无论是谁还在玩 - 这是DW服务器的整合任务,它应该为webserver创建表(这是精简的)

    2)我怎么能快速地在网络服务器上提取(所以(1)的表格设计应该考虑到这一点。我们不是在谈论很多玩家在这里我需要这个信息,也许100?(所以然后我可以按玩家ID分区,或者只创建单个表格)


    • Datawarehouse:postgreSQL 9.2(48GB,SSD)
    • 网络服务器:mySQL 5.5(4GB Ram,SSD)

      • 主表:gameid BIGINT,participID,结果INT,参与者ID的外键(到参与者表)
    • DW服务器将保存主表,DW服务器还应准备合并/提取的表(处理能力,ssd空间不是 一个问题)
    • 网络服务器应该持有相关表格(仅适用于100个 我需要信息的玩家)并在非常查询这些数据 高效的方式

    在网络服务器上高效查询&gt;&gt; DW服务器的工作量)


    我认为这很重要,很抱歉我没有把它包括在内。

    DW服务器上的数据每天更新,但我不需要每天完整地查询整个“主表”。设置允许我只合并从不值。例如:昨天合并达到ID 500,当前ID = 550,所以今天我只合并501-550。

2 个答案:

答案 0 :(得分:0)

听起来你只想要一个自我加入:

对所有参与者:

SELECT x.gameID, x.participID, x.results, y.participID, y.results
FROM table as x
JOIN table as y
  ON T1.gameID = T2.gameID
WHERE x.participID <> y.participID

这样做的缺点是你会让每个参与者都参与每场比赛。

对于2个特定参与者:

 SELECT x.gameID, x.results, y.results
    FROM (SELECT gameID, participID, results 
          FROM table 
          WHERE t1.participID = 'x'
                and results <> 0)
           as x
    JOIN (SELECT gameID, participID, results 
          FROM table 
          WHERE t1.participID = 'y'
                and results <> 0)
          as y
      ON T1.gameID = T2.gameID

您可能不需要在查询中选择participantID,具体取决于您对结果的处理方式。

答案 1 :(得分:0)

根据您的数据库(以及我对问题的理解),这是另一个可能有效的想法:

SELECT *
FROM   table a
WHERE  participID = 'x'
   AND EXISTS (
      SELECT 1 FROM table b
      WHERE b.participID = 'y'
        AND b.gameID=a.gameID
     );

假设您在两列(participID和gameID)上有索引,那么性能应该不错。

我将它与此进行比较,看看哪个运行得更快:

SELECT *
FROM   table a
JOIN (
   SELECT gameID
   FROM   table
   WHERE  participID = 'y'
   GROUP BY gameID
   ) b
ON a.gameID=b.gameID
WHERE  a.participID = 'x';