#ruby-on-rails #sql-server #ruby #ruby-on-rails-3 #sql-server-2008
#ruby-on-rails #sql-сервер #ruby #ruby-on-rails-3 #sql-server-2008
Вопрос:
У меня есть две таблицы, и я хочу сравнить данные между ними и выбрать данные из одной таблицы, которых нет в другой. У меня уже есть код, который работает в управлении SQL Server, но мне нужно преобразовать его в Rails или мне нужно иметь возможность использовать необработанный код SQL в моем коде. Вот код:
select * from app_servers
where not exists
( select app, environment, server
from stagings
where stagings.server = app_servers.server_id
AND
stagings.environment = app_servers.environment_id
AND
app_servers.app_id = stagings.app
)
Заранее спасибо
Комментарии:
1. И у вас есть модель для App_Servers или вы начинаете с нуля?
Ответ №1:
Почему вы хотите ее преобразовать? Вы можете использовать его как есть
AppServer.where(" not exists
( select app, environment, server
from stagings
where stagings.server = app_servers.server_id
AND
stagings.environment = app_servers.environment_id
AND
app_servers.app_id = stagings.app
)
")
Комментарии:
1. Можно привести аргумент в пользу того, что вы всегда должны, по крайней мере, пытаться перевести свой sql в AREL. Это заставляет мою голову немного кружиться, потому что я не знаю о моделях и возможных ассоциациях здесь. Я не говорю, что не делайте того, что вы предлагаете, но я бы сначала попробовал использовать синтаксис запроса ActiveRecord. руководство по Arel
2. Я согласен с вами, возможно, в этом конкретном случае не так много пользы, но в целом это действительно удобно. Итак, смотрите Обновление.
3. @Bohdan Pohorilets приятно, что это сработало для меня 😉 Я попробую внести изменения без
select * from app_servers
этого и дам вам знать.
Ответ №2:
Если я правильно понимаю, у вас есть две модели, AppServer
Staging
и обе имеют среду, сервер и приложение. Вы ищете AppServer
‘ы, которые не имеют соответствующего Staging
.
Итак, ваши модели будут выглядеть так:
class AppServer
belongs_to :server
belongs_to :environment
belongs_to :app
end
class Staging
belongs_to :server
belongs_to :environment
belongs_to :app
end
Но то, что вы на самом деле хотели бы, это что-то вроде
class AppServer
belongs_to :server
belongs_to :environment
belongs_to :app
has_one :staging
end
что было бы действительно легко протестировать. Что-то вроде:
AppServer.where(:staging_id => nil)
Таким образом, вы могли бы рассмотреть возможность реформирования вашей модели данных, чтобы упростить это.
Это было бы не слишком сложно: добавьте один столбец и для каждого app_server найдите соответствующую промежуточную стадию.
Но предположим, что у вас нет никакого контроля над вашей моделью данных, вам нужно было бы написать что-то вроде
class AppServer
has_many :stagings, finder_sql => 'select * from stagings where server=#{server_id} and environment=#{environment_id} and app=#{app_id}'
Примечание: вы должны использовать одинарные кавычки!!
Это, по крайней мере, позволило бы вам получить доступ к чему-то вроде
app_server = AppServer.first
app_server.stagings
К сожалению, это не позволяет вам написать что-то вроде
AppServer.where(:stagings => nil)
Чтобы найти все AppServer
без промежуточной обработки, и вы не можете преобразовать схему, вам нужно будет сделать что-то вроде
AppServer.where(" not exists
( select app, environment, server
from stagings
where stagings.server = app_servers.server_id
AND
stagings.environment = app_servers.environment_id
AND
app_servers.app_id = stagings.app
)"
)
Так что на самом деле, в конце концов, я не нашел нового и улучшенного способа использования arel.
Но я показал несколько способов, позволяющих использовать некоторые помощники rails, и, во-вторых, кажется хорошим подходом, если это возможно (даже с использованием представлений), преобразовать вашу модель данных в более удобную для rails модель. Одна из веских причин заключается в том, что rails-способ создания моделей данных на самом деле является довольно хорошим способом.
Комментарии:
1. Вау, это круто, чувак. Большое спасибо за помощь. Удалось запустить его и запустить через справку @Bohdan Pohorilets, но, несмотря на это, я обязательно посмотрю на ваш ответ и повторно использую его в будущем 😉