1

我已经尝试了一段时间,但似乎无法在 Activerecord 中正确使用它。

asset_id给定一个和对的数组asset_type,查询一个同时具有这两个属性的类,仅当两者都asset_id匹配asset_type时。

所以给定数组

[[4,"Logo"],[1,"Image"]]

我想生成 SQL

SELECT "asset_attachments".* FROM "asset_attachments" WHERE ((asset_id,asset_type) IN ((4,'Logo'),(1,'Image')))

我可以通过使用 where 手动输入字符串来做到这一点:

AssetAttachment.where("(asset_id,asset_type) IN ((4,'Logo'),(1,'Image'))")

但我正在尝试将它与任意长度和资产类型/id 的数组一起使用。

到目前为止我已经尝试过

AssetAttachment.where([:asset_id, :asset_type] => [[4,"Logo"],[1,"Image"]])

NoMethodError: undefined method `to_sym' for [:asset_id, :asset_type]:Array

AssetAttachment.where("(asset_id,asset_type)" => [[4,"Logo"],[1,"Image"]])

ActiveRecord::StatementInvalid: PG::Error: ERROR: column asset_attachments.(asset_id,asset_type) does not exist

AssetAttachment.where("(asset_id,asset_type) IN (?,?)",[[4,"Logo"],[1,"Image"]])

ActiveRecord::PreparedStatementInvalid: wrong number of bind variables (1 for 2) in: (asset_id,asset_type) IN (?,?)

有谁知道如何做到这一点?提前致谢

4

1 回答 1

1

集合与数组

问题的核心是:您以不可能的方式混合集合数组

elem IN (...).. 期待一个集合
elem = ANY(...).. 需要一个数组

您可以使用unnest()将数组转换为集合。
您可以使用聚合函数array_agg()将集合转换为数组。

错误

在这里,您试图从 形成一个数组(asset_id, asset_type)

AssetAttachment.where([:asset_id, :asset_type] => [[4,"Logo"],[1,"Image"]])

.. 这是不可能的,因为数组必须由相同的类型组成,而我们显然要处理数字和字符串常量(您将实际类型保密)。

在这里,您通过双引号将其强制"(asset_id, asset_type)"单列名称:

AssetAttachment.where("(asset_id,asset_type)" => [[4,"Logo"],[1,"Image"]])

最后,在这里您尝试为两个提供单个绑定变量?

AssetAttachment.where("(asset_id,asset_type) IN (?,?)",[[4,"Logo"],[1,"Image"]])

有效的 SQL

在纯 SQL 中,这些都可以工作:

SELECT * FROM asset_attachments
WHERE  (asset_id, asset_type) IN ((4, 'Logo'), (1, 'Image'));

SELECT * FROM asset_attachments
WHERE  (asset_id, asset_type) IN (VALUES(4, 'Logo'), (1, 'Image'));

SELECT * FROM asset_attachments
WHERE  (asset_id, asset_type) = ANY (ARRAY[(4, 'Logo'), (1, 'Image')]);

如果您有一长串可能的匹配项,那么显式JOIN会更快:

SELECT *
FROM   asset_attachments
JOIN   (VALUES(4, 'Logo'), (1, 'Image')) AS v(asset_id, asset_type)
                                       USING (asset_id, asset_type)

AR 的有效语法

我是 Postgres 方面的专家,但 AR 并不多。这种简单的形式可能会起作用:

AssetAttachment.where("(asset_id,asset_type) IN ((?,?),(?,?))", 4,"Logo",1,"Image")

不确定这是否可行,也不确定单引号或双引号:

AssetAttachment.where((:asset_id, :asset_type) => [(4,'Logo'),(1,'Image')])
于 2013-05-26T16:03:16.147 回答