2015-02-03 2 views
0

Я работаю над изучением Ruby on Rails и задаю некоторые конкретные вопросы об активных рельсах и их преобразованиях SQL.В чем разница между выбором пользователей. * И выбором каждого столбца?

FYI, я использую PostgreSQL и пользователя модели имеет много статусов, и я хотел бы заказать пользователей на основе created_at колонка состояний. Хотя я нашел решение, User.includes(:statuses).order('statuses.created_at desc'), у меня все еще есть некоторые (возможно, связанные между собой) вещи, которые я плохо понимаю.

1) На рельсах консоли, (я упрощены для лучшего readibility)

User.joins(:statuses).to_sql производит "SELECT users.* FROM users INNER JOIN statuses ON statuses.user_id = users.id".

User.includes(:statuses).references(:statuses).to_sql производит "SELECT users.id AS t0_r0, ...(simplified)... statuses.created_at AS t1_r3 FROM users LEFT OUTER JOIN statuses ON statuses.user_id = users.id"

Какова разница между выбором пользователей. * И выбор каждого отдельного столбца?

2) Кроме того, на рельсы консоли

User.joins(:statuses).size производит SELECT COUNT(*) FROM users INNER JOIN statuses ON statuses.user_id = users.id => 155.

User.includes(:statuses).references(:statuses).size производит SELECT COUNT(DISTINCT users.id) FROM users LEFT OUTER JOIN statuses ON statuses.user_id = users.id => 16.

Почему включает автоматически содержит отчетливое положение в то время как присоединяется не?

3) Я попытался получить отчетливый пользователей по заказу statuses.created_at с статусами соединяемых на пользователей.

Я использовал этот раздел: User.joins(:statuses).select('users.*, statuses.created_at').order('statuses.created_at desc').distinct. (Я должен использовать . Status status.created_at из-за PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list)

Но этот пункт не удаляет дублирование! Хотя User.joins(:statuses).select!('users.*, statuses.created_at').order('statuses.created_at desc').distinct.size производит , когда я его фактически выполняю, я вижу много дубликатов.

Он выдает инструкцию SQL: SELECT DISTINCT users.*, statuses.created_at FROM users INNER JOIN statuses ON statuses.user_id = users.id ORDER BY statuses.created_at desc, и он показывает следующее изображение.

Result of User.joins(:statuses).select!('users.*, statuses.created_at').order('statuses.created_at desc').distinct

Как вы видите, это показывает дупликации моих записей.

Итак, мой третий вопрос: Почему отдельная статья не устраняет дублирования (и почему размер показывает отличный результат)?

Заранее спасибо!

ответ

1

Метод joins просто генерирует для вас соединение SQL. Любой отдельный пользователь может быть присоединен к нескольким статусам - это то, что объединяет, если это не то, что вам нужно, тогда вам решать, как с этим бороться. Отборные оговорка по умолчанию users.* так, что вы нечаянно не в конечном итоге с одинаковыми именами столбцов через обе таблицы затенения друг с другом (например, в id колонке)

includes с другой стороны, для жадной загрузки ассоциации. То, что это иногда выполняется с соединением, - это всего лишь дополнительная информация - в обработке результата есть дополнительный код, так что в результирующем наборе каждый пользователь имеет ровно один раз (а также данные статуса, переданные в ассоциацию). Включает также псевдонимы всех имен столбцов для обработки столбцов с одинаковым именем

Наконец, ваше отдельное предложение не удаляет дубликаты, потому что строки не идентичны - столбец statuses.created_at включен, который будет отличаться для большинства строк.

Метод size проигнорирует выберите пункт и поэтому рассчитывает на users.id - в этом случае отчетливым будет только каждый пользователь учитывается один раз