我想执行以下查询:
query = "select v.price, v.quantity, p.title, v.product_id from variants v join products p on (v.product_id = p.id) where (v.price,v.product_id) in (select min(price),product_id from variants group by product_id);"
当我在rails控制台中results = ActiveRecord::Base.connection.execute(query)
时,我得到:
ActiveRecord::StatementInvalid: SQLite3::SQLException: near ",": syntax error: select v.price, v.quantity, p.title, v.product_id from variants v join products p on (v.product_id = p.id) where (v.price,v.product_id) in (select min(price),product_id from variants group by product_id)
我确信所有的逗号都已到位,并且该语句至少对Oracle来说非常好。我的错误在哪里?
答案 0 :(得分:2)
似乎sqlite3没有超过运算符的多个值(where (v.price,v.product_id) in (select min(price),product_id...
)
通过讨论背后的问题是:
我需要获得每种产品的最低价格(在Variants中) 名称(在产品中)和数量(在变体中)
基于此,我推荐这个SQL语句:
SELECT min(`v`.`price`) AS 'min_price', `v`.`quantity`, `p`.`title`, `v`.`product_id` FROM `variants` AS 'v' INNER JOIN `products` AS 'p' ON (`v`.`product_id` = `p`.`id`) GROUP BY `product_id`
或人类可读版本中的相同陈述:
SELECT
min(`v`.`price`) AS 'min_price',
`v`.`quantity`, `p`.`title`, `v`.`product_id`
FROM `variants` AS 'v'
INNER JOIN `products` AS 'p'
ON (`v`.`product_id` = `p`.`id`)
GROUP BY `product_id`
我不使用rails和活动记录,我使用续集来获得此解决方案。这是我测试代码的完整脚本:
require 'sequel'
DB = Sequel.sqlite('test.db')
Sequel.extension :core_extensions
Sequel.extension :pretty_table
#if called 2nd time with a db-file
DB.drop_table(:variants) if DB.table_exists?(:variants)
DB.drop_table(:products) if DB.table_exists?(:products)
DB.create_table :products do |t|
primary_key :id
t.string :title
t.string :description
t.timestamps null: false
end
DB.create_table :variants do |t|
primary_key :id
t.boolean :is_active
t.integer :price
t.integer :quantity
t.timestamps null: false
foreign_key :product_id, :products
end
class Product < Sequel::Model; end
class Variant < Sequel::Model; end
10.times do |g|
Product.create(title: "Prod %02i" % g, description: "Who Cares..")
end
100.times do |c|
Variant.create(
price: (rand(100)).ceil, quantity: (rand(10).ceil).floor ,
product_id: Product[rand(1..10).floor].id
)
end
puts DB.tables
sel = DB[:variants.as(:v)]
.select(Sequel.function(:min,:v__price).as(:min_price), :v__quantity, :p__title, :v__product_id)
.join(:products.as(:p), :v__product_id => :p__id)
.group_by(:product_id)
puts sel.sql
Sequel::PrettyTable.print(sel)
结果是:
SELECT min(`v`.`price`) AS 'min_price', `v`.`quantity`, `p`.`title`, `v`.`product_id` FROM `variants` AS 'v' INNER JOIN `products` AS 'p' ON (`v`.`product_id` = `p`.`id`) GROUP BY `product_id`
+---------+----------+--------+-------+
|min_price|product_id|quantity|title |
+---------+----------+--------+-------+
| 1| 1| 5|Prod 00|
| 12| 2| 9|Prod 01|
| 21| 3| 6|Prod 02|
| 1| 4| 0|Prod 03|
| 34| 5| 8|Prod 04|
| 11| 6| 8|Prod 05|
| 14| 7| 9|Prod 06|
| 7| 8| 8|Prod 07|
| 11| 9| 8|Prod 08|
| 21| 10| 8|Prod 09|
+---------+----------+--------+-------+
(执行时的值可能不同,数据创建中有随机值)。