如何在Rails中执行此SQL查询?

时间:2014-03-18 18:41:32

标签: sql ruby-on-rails ruby join controller

如何在Rails中执行此SQL查询?

我有三张桌子,我试图加入。我很确定我已在模型中正确连接它们。

我有一些联合表,在这种情况下,有一个"所有权"具有用户ID和游戏ID的表。它与#34;游戏内心联系在一起。表和"用户"表。游戏表具有游戏信息,并且具有与控制台表连接的console列。控制台表是数据库中的所有控制台。这样,当我显示游戏时,我可以显示它所属的控制台。

我创建了一个网络界面来跟上我的视频游戏集。我有它在PHP中工作,但我将所有内容都转换为Ruby on Rails。我现在要做的是,在库存页面上,我想显示用户有游戏的控制台,以便用户可以选择控制台并过滤显示的游戏,仅显示该控制台的游戏。

例如,主库存页面显示用户拥有的每个游戏。在右侧,有一个侧边栏,其中包含用户可以玩游戏的控制台。如果用户只想看到他为N64制作的游戏,他点击N64并过滤显示屏以仅显示N64游戏。

除非用户拥有该控制台的游戏,否则我不想在侧边栏上显示控制台。

这是我想要工作的SQL查询:

select distinct console_general.eng_name from ownership inner join games on games.id=ownership.games_id inner join console_general on console_general.console_id=games.console_general_id;

以下是我的表格:

mysql> describe games;
+--------------------+------------+------+-----+---------+----------------+
| Field              | Type       | Null | Key | Default | Extra          |
+--------------------+------------+------+-----+---------+----------------+
| id                 | int(11)    | NO   | PRI | NULL    | auto_increment |
| ean                | mediumtext | YES  |     | NULL    |                |
| eng_title          | mediumtext | YES  |     | NULL    |                |
| jap_title          | mediumtext | YES  |     | NULL    |                |
| console_general_id | int(11)    | YES  | MUL | NULL    |                |
| region_id          | int(11)    | YES  | MUL | NULL    |                |
| image              | int(11)    | YES  | MUL | NULL    |                |
+--------------------+------------+------+-----+---------+----------------+

mysql> describe ownership;
+----------------------+------------+------+-----+---------+-------+
| Field                | Type       | Null | Key | Default | Extra |
+----------------------+------------+------+-----+---------+-------+
| user_id              | int(11)    | NO   |     | 0       |       |
| games_id             | int(11)    | YES  | MUL | NULL    |       |
| own                  | tinyint(1) | YES  |     | NULL    |       |
| complete             | tinyint(1) | YES  |     | NULL    |       |
| box_condition        | int(11)    | YES  | MUL | NULL    |       |
| game_condition       | int(11)    | YES  | MUL | NULL    |       |
| manual_condition     | int(11)    | YES  | MUL | NULL    |       |
| inserts_condition    | int(11)    | YES  | MUL | NULL    |       |
| notes                | text       | YES  |     | NULL    |       |
| spine_card_condition | int(11)    | YES  | MUL | NULL    |       |
| count                | int(11)    | NO   |     | 1       |       |
+----------------------+------------+------+-----+---------+-------+

mysql> describe console_general
    -> ;
+------------+---------+------+-----+---------+----------------+
| Field      | Type    | Null | Key | Default | Extra          |
+------------+---------+------+-----+---------+----------------+
| console_id | int(11) | NO   | PRI | NULL    | auto_increment |
| eng_name   | text    | YES  |     | NULL    |                |
| jap_name   | text    | YES  |     | NULL    |                |
+------------+---------+------+-----+---------+----------------+

这是我的控制器:

class InventoryController < ApplicationController
  def test

    # These work fine
    @user = User.find_by(params[:id])
    @ownership = Ownership.where(user_id: 1)

    # This is the variable I've been working on, not sure if I'm on the right track or not.
    # @console =  Ownership.joins(games: {console_general: :console_id})
  end
end

这是我的模特:

class Ownership < ActiveRecord::Base
self.pluralize_table_names = false

belongs_to :games

Ownership.joins(:games)

end

class Games < ActiveRecord::Base
belongs_to :console_general
belongs_to :region
belongs_to :image
has_many :ownership

Games.joins(:region, :console_general, :image)
end

lass ConsoleGeneral < ActiveRecord::Base
self.pluralize_table_names = false

has_many :games
has_many :accessories
end

我希望这是有道理的。

编辑:

稍微操纵给定的答案,我能够得到它。模型关联是正确的,但控制器实例变量最初没有工作,这就是我做的事情

Ownership.joins(:games => :console_general).uniq.pluck(:eng_name)

Ownership.joins(:games => :console_general).uniq.pluck(:eng_name)

这很有效。谢谢你所有的帮助。

2 个答案:

答案 0 :(得分:0)

class User < ActiveRecord::Base
  has_many :ownerships
  has_many :games, through: :ownerships
end

class Ownership < ActiveRecord::Base
  belongs_to :user
  belongs_to :game
end

class Game < ActiveRecord::Base
  has_many :ownerships
  has_many :users, through: :ownerships
  belongs_to :console_general
end

class ConsoleGeneral < ActiveRecord::Base
  has_many :games
end

Railsguide

然后

select distinct console_general.eng_name from ownership 
inner join games ongames.id=ownership.games_id 
inner join console_general on console_general.console_id=games.console_general_id

...如果要看到所有游戏都有任何游戏那么你就可以做到:

ConsoleGenerals.joins(:games).uniq.pluck(:eng_name)

pluck仅选择eng_name,uniq产生'select distinct',而join(:games)将强制存在相关游戏。

或者,如果您想限制拥有的游戏

ConsoleGenerals.joins(:games => :ownerships).uniq.pluck(:eng_name)

答案 1 :(得分:0)

class ConsoleGeneral < ActiveRecord::Base
  ...
  scope :with_owned_games, -> { joins(:games).merge(Games.with_ownerships) }
end

class Games < ActiveRecord::Base
  ...
  scope :with_ownerships, -> { joins(:ownership) }
  scope :with_certain_owner, -> { |owner_id| joins(:ownership).where(user_id: owner_id) }
end

拥有所有权游戏的ConsoleGeneral:

ConsoleGeneral.with_owned_games

仅限Uniq eng_names:

ConsoleGeneral.with_owned_games.select(:eng_name).uniq

ConsoleGeneral,其游戏属于具有id = some_user_id的用户:

ConsoleGeneral.with_certain_owner(some_user_id)

仅限Uniq eng_names:

ConsoleGeneral.with_certain_owner(some_user_id).select(:eng_name).uniq