2011-09-11 55 views
3

我的模型Rails 3/SQL - 一個複雜的「存在?」查詢

class Team < ActiveRecord::Base 
    has_many :team_players 
    has_many :players, :through => :team_players 
end 

class TeamPlayer < ActiveRecord::Base 
    belongs_to :team 
    belongs_to :player 
end 
  • 團隊可以有不同數量的玩家
  • 玩家可以在許多球隊
  • 檢索TEAM_ID如果它已經存在< - 我的問題

當創建一個新的團隊時,我基本上選擇了嵌套形式的多個玩家。在創建之後,我需要檢查是否已經存在具有精確球員構成的球隊。

實施例:

  • 球隊1:(ID 1)和(ID 2)
  • 隊2:(ID 1),(ID 2 )和ç(ID 3)

比方說,我創建了一個新的團隊AB,那麼我需要查詢以某種方式告訴我它是否存在,通過返回team_id或其他東西或空的結果。

我打得四處類似於此的查詢,但沒有令人滿意的結果

SELECT *, count(id) as c FROM "team_players" WHERE player_id IN (1,3) GROUP BY team_id HAVING c = 2 

回答

1

我覺得你可以在兩個步驟做到這一點:

  1. 查找擁有所有的球隊你正在看的球員。
  2. 檢查這些球隊是否擁有比您正在查看的球員更多的球員。

這就轉化成了這樣:

select team_id 
from team_players 
where team_id in (
    select team_id 
    from team_players 
    where player_id in (1,3) 
    group by team_id 
    having count(player_id) = 2 
) 
group by team_id 
having count(player_id) = 2 

team_players有鑑於此:

team_id|player_id 
    1 | 1 
    1 | 3 
    1 | 4 
    2 | 1 
    2 | 3 
    3 | 3 

上面的查詢表示team_id = 2而且也完全匹配。您正在使用的查詢爲您提供了包含相關球員的球隊作爲子集,而不是與球員相關的球隊。

如果你只是想知道,如果這樣的球隊存在,那麼包裝在select_rows調用,查詢,就大功告成了:

class Team < ActiveRecord::Base 
    # players is an array of Fixnum player IDs 
    def self.team_exist?(players) 
     return false if(!players.present?) 
     connection.select_rows(%Q{ 
      select team_id 
      from team_players 
      where team_id in (
       select team_id 
       from team_players 
       where player_id in (#{players.join(',')}) 
       group by team_id 
       having count(player_id) = #{players.length} 
      ) 
      group by team_id 
      having count(player_id) = #{players.length} 
     }).present? 
    end 
end 

#{players.join(',')}插值假定team_exist?被賦予的長整數數組等等您需要正確清理調用者中的數據,或者在connect.select_rows調用之前添加players = players.map(&:to_i)以清除team_exist?中的數據。

+0

謝謝!我沒有使用connection.select_rows,因爲我想獲取實際的team_id值。但查詢本身工作得很好。 (除了你忘了在最後一部分中定義'c') – Frexuz

+0

@Frexuz:'有c ...'應該是'有數(player_id)...'對嗎?我正在翻譯我的廢話名字和你的真實姓名。 –

+0

是的,這是正確的:) – Frexuz