Rails 在 find_by_sql 中使用 sql 变量

发布于 2024-11-16 01:32:08 字数 1069 浏览 3 评论 0原文

我有这个查询:

SET @current_group = NULL; 
SET @current_count = 0; 
SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c 
FROM notifies 
G    ROUP BY user_id, c 
ORDER BY id desc LIMIT 0 , 10

如果我启动它它可以工作,

但是如果我将它放入 find_by_sql 方法中,例如:

Notify.find_by_sql("SET @current_group = NULL; SET @current_count = 0; SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c FROM notifies GROUP BY user_id, c ORDER BY id desc LIMIT 0 , 10")

它返回此错误:

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SET @current_count = 0; SELECT user_id, MIN( created_at ) as created_at, CASE WH' at line 1:

我该怎么办?

谢谢

I have this query:

SET @current_group = NULL; 
SET @current_count = 0; 
SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c 
FROM notifies 
G    ROUP BY user_id, c 
ORDER BY id desc LIMIT 0 , 10

If i launch it it works

but if i put it in a find_by_sql method like:

Notify.find_by_sql("SET @current_group = NULL; SET @current_count = 0; SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c FROM notifies GROUP BY user_id, c ORDER BY id desc LIMIT 0 , 10")

It returns this error:

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SET @current_count = 0; SELECT user_id, MIN( created_at ) as created_at, CASE WH' at line 1:

How can i do?

thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

路弥 2024-11-23 01:32:08

这是因为 find_by_sql 仅适用于单个语句< /a>

设置变量发生在单独的语句中。 set 具体位于数据库管理部分,编号 12.4.4,select 位于数据操作节,编号 12.2.7。控制台(通常)允许多个语句,并保留变量,但 ActiveRecord 查询不允许。

为了允许多个语句,我认为您必须保持与数据库的持久连接,而 Rails 不会这样做(编辑:通常)。但我对此不确定 - 如果其他人知道,我希望有一个更明确的原因。

编辑:实际上,我有一个解决方案给你。试试这个:

items = YourModel.transaction do
  YourModel.connection.execute("SET @current_group = NULL;")
  YourModel.connection.execute("SET @current_count = 0;")
  # this is returned, because it's the last line in the block
  YourModel.find_by_sql(%Q|
    SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c 
    FROM notifies 
    GROUP BY user_id, c 
    ORDER BY id desc LIMIT 0 , 10
  |)
end

所有这些都在单个事务中运行,事务块内的任何变量/设置都将在查询之间保留。不过,每个查询仍然受限于单个语句。可能有一种方法可以在没有实际交易包装整个集合的情况下做到这一点,但我还没有寻找它 - 很可能你想要一个,或者如果你知道你不想要的话,你现在有一个非常具体的东西要寻找。

享受!

It's because find_by_sql only works with a single statement.

Setting variables happen in separate statements. set specifically is in the Database Administration section, number 12.4.4, and select is in Data Manipulation section, number 12.2.7. Consoles (usually) allow multiple statements, and keep the variables around, but ActiveRecord queries do not.

To allow multiple statements, I think you have to maintain a persistent connection with the database, which Rails doesn't do (edit: normally). But I'm not certain about that - if anyone else knows, I'd love a more definite reason.

Edit: actually, I have a solution for you. Try this:

items = YourModel.transaction do
  YourModel.connection.execute("SET @current_group = NULL;")
  YourModel.connection.execute("SET @current_count = 0;")
  # this is returned, because it's the last line in the block
  YourModel.find_by_sql(%Q|
    SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c 
    FROM notifies 
    GROUP BY user_id, c 
    ORDER BY id desc LIMIT 0 , 10
  |)
end

All those run in a single transaction, and any variables / settings inside the transaction block will persist between queries. You're still bound to a single statement per query though. There might be a way to do it without an actual transaction wrapping the whole set, but I haven't looked for it - most likely you want one, or you now have a very specific thing to look for if you know you don't.

Enjoy!

紫竹語嫣☆ 2024-11-23 01:32:08

根据 API,它的语法如下:

Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id,  start_date]

因此,您可能想尝试将其放入数组中,而不是使用括号。

Notify.find_by_sql ["SET @current_group = NULL; SET @current_count = 0; SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c FROM notifies GROUP BY user_id, c ORDER BY id desc LIMIT 0 , 10"]

Accordingly to the API it is this syntax:

Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id,  start_date]

So you might want to try putting it into an array instead of using parenthesis.

Notify.find_by_sql ["SET @current_group = NULL; SET @current_count = 0; SELECT user_id, MIN( created_at ) as created_at, CASE WHEN @current_group = user_id THEN @current_count WHEN @current_group := user_id THEN @current_count := @current_count + 1 END AS c FROM notifies GROUP BY user_id, c ORDER BY id desc LIMIT 0 , 10"]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文