Несколько агрегированных запросов с использованием гема сиквела
Можно ли использовать продолжение для выполнения запроса, как это:
select (select count(*) from users where blah = 'blah') as "users",
(select count(*) from contacts where blah = 'blah') as "contacts"
Я знаю, что могу выполнять эти запросы один раз, используя продолжение, но я бы хотел выполнить их все одновременно.
4 ответа
Вы можете выполнить этот запрос без написания необработанного SQL с помощью следующего:
dataset = DB.select {[
DB[:users].where(blah: 'blah').select { count('*') }.as(:users),
DB[:contacts].where(blah: 'blah').select { count('*') }.as(:contacts)
]}
dataset.first
# => { users: X, contacts: Y }
dataset.sql
# => "SELECT (SELECT count('*') FROM \"users\" WHERE (\"blah\" = 'blah')) AS \"users\",
# (SELECT count('*') FROM \"contacts\" WHERE (\"blah\" = 'blah')) AS \"contacts\""
Да, вы можете сделать это хорошо с жемчужиной сиквела.
require 'sequel'
DB = Sequel.sqlite # memory database
DB.create_table :users do
primary_key :id
String :name
end
users = DB[:users] # Create a dataset
users.insert(:name => 'jim')
DB.create_table :contacts do
primary_key :id
String :name
end
contacts = DB[:contacts] # Create a dataset
contacts.insert(:name => 'first')
DB['select (select count(*) from users where name = "jim") as users,
(select count(*) from contacts where name = "first") as contacts'].each do |row|
puts row
end
#{:users=>1, :contacts=>1}
Однако следует отметить, что не стоит включать необработанные строки в метод сиквела. Их можно извлечь следующим образом:
DB['select (select count(*) from users where name = ?) as users,
(select count(*) from contacts where name = ?) as contacts, 'jim', 'first'].each do |row|
puts row
end
Также, как отмечено в другом ответе, вы можете выразить этот запрос полностью, не прибегая к SQL, который больше соответствует духу модуля.:
dataset = DB.select {[
DB[:users].where(name: 'jim').select { count('*') }.as(:users),
DB[:contacts].where(name: 'first').select { count('*') }.as(:contacts)
]}
dataset.sql
# SELECT (SELECT count('*') FROM `users` WHERE (`name` = 'jim')) AS 'users', (SELECT count('*') FROM `contacts` WHERE (`name` = 'first')) AS 'contacts'
dataset.first
# {:users=>1, :contacts=>1}
Вы можете выполнить, как вы упомянули выше, с вашим запросом проблем нет. Я выполнил то же самое, и это было выполнено без каких-либо проблем..
ниже было то, что я выполнил
select( SELECT count(*) FROM `abcde` where `User_ID`=4001) as "aa",
(SELECT count(*) FROM `abcdef` where `User_ID`=4018) as "bbb"
Результаты:
aa bbb
181 364
Вам нужно добавить * после выбора и может быть некоторые скобки:
select * from ((select count(*) from users where blah = 'blah') as "users",
(select count(*) from contacts where blah = 'blah') as "contacts")