2014-05-18 18 views
1

我想存儲有關遊戲Dominion遊戲的一些信息。你不需要知道很多關於這場比賽,除了:如何設計用於存放Dominion卡的數據庫?

  • 大約有200獨特的卡
  • 每場比賽僅包括這些卡片十個,或有時11

我我會跟蹤更多關於每場比賽(誰玩,誰贏了等),但我遇到的麻煩是與「供應」(這個遊戲中包含的十個卡)一起工作。

我想我要三張表,像card_namesupplygame

card_name   supply      game          

id | name  supply | card  game | supply | player1 | player2 | ... 
----+--------- --------+------ ------+--------+---------+---------+----- 
    1 | Village   1 | 1   301 |  1 | 'Mike' | 'Tina' | ... 
    2 | Moat    1 | 3  
    3 | Witch   1 | 200  
... | ...   ... | ...  
200 | Armory  

我覺得這是代表「邁克和Tina玩遊戲含有村一個合理的方式,女巫,軍械庫和其他一些卡,我沒有打擾到這個例子「。鑑於這種結構(或其他一種,如果你認爲我的行爲不好),我想運行諸如「哪些遊戲有女巫和村莊,但不是護城河?」等查詢。也就是說,我想指定一些任意數量的「包含這些X卡片,排除這些Y卡片」,並在game表格中查找符合條件的遊戲。

我認爲這是一個經典的一對多關係,供應有多張卡片,但我不明白用多張卡片搜索供應的正確方法。

回答

2

您的數據結構是合理的。我可能會建議你也想要一個game_users表,所以用戶不在單獨的列中列出。如果遊戲擁有不同數量的用戶,這一點尤其重要。但是,這方面與您的問題無關。

您想解決「set-set-set」子查詢。您的結構非常有用,而supply表提供了所需的基本信息。

所以,一個查詢以獲得「魔女」適當的「供給」記載,「村」,而不是「護城河」看起來像:

select supplyid 
from supplies s join 
    cards c 
    on s.cardid = c.cardid 
group by supplyid 
having sum(case when cardname = 'Witch' then 1 else 0 end) > 0 and 
     sum(case when cardname = 'Village' then 1 else 0 end) > 0 and 
     sum(case when cardname = 'Moat' then 1 else 0 end) = 0; 

首先說明,我改了名字,所以id列包含單詞「id」,表名稱爲複數形式。

having子句中的每個條件表示卡上的一個條件。你可以調整這個由加盟games獲得遊戲信息:

select g.gameid 
from supplies s join 
    cards c 
    on s.cardid = c.cardid join 
    games g 
    on g.supplyid = s.gameid 
group by g.gameid 
having sum(case when cardname = 'Witch' then 1 else 0 end) > 0 and 
     sum(case when cardname = 'Village' then 1 else 0 end) > 0 and 
     sum(case when cardname = 'Moat' then 1 else 0 end) = 0; 
+0

這'有sum'解決方案似乎是它需要的所有遊戲的線性掃描,對不對?我有足夠小的數據集,這可能是可以接受的,但我希望能利用索引的東西。 – amalloy

+0

@amalloy。 。 。 Postgres不是MySQL。它實際上實現了合理的聚合算法。在這種情況下,你可以在'女巫','村','護城河'中加入一個名字,並且可以使用索引來減少搜索空間。 –

+0

有道理。謝謝! – amalloy