2

我有一个表 ,transactions可能包含重复项(对我们来说,重复项是Transaction具有相同account_iddate, 和amount)。

我的英语功能要求是“我想查看所有存在超过 1 笔具有相同 account_id、日期和金额的交易的交易”。

暂时放弃 AREL,我在 SQL 中产生了这样的东西:

SELECT * FROM transactions t1, transactions t2
    WHERE t1.id != t2.id 
      AND t1.date = t2.date
      AND t1.amount = t2.amount
      AND t1.account_id = t2.account_id

我正在使用 Rails 3.2.x 和 Postgres。

最初,我在 AREL 中尝试过:

Transaction.group(:account_id, :date, :amount).having("count(id) > 1")

但这给了我关于聚合函数的 SQL 错误:

PG::Error: ERROR:  column "transactions.id" must appear in the GROUP BY clause or be used in an aggregate function

.. 这令人沮丧,因为我希望 group by 子句中的 ID - 重点是我希望在检查欺骗时忽略 ID。

如果有人能指出我需要将其设为范围的 AREL 的正确方向,我将不胜感激——find_by_sql当您需要记录时非常好,但我正在尝试创建 ActiveAdmin 范围——它不喜欢数组.

4

3 回答 3

1

您可以在 ActiveRecord 事务模型中使用 sql 定义范围,如下所示:

scope :duplicate_transactions, where(<<-eosql.strip)
  transactions.id IN (
      SELECT 
          t1.id 
      FROM 
          transactions t1, transactions t2
      WHERE 
          t1.id != t2.id AND
          t1.date = t2.date AND
          t1.amount = t2.amount AND
          t1.account_id = t2.account_id
  )
eosql

但是随后涉及到 id.. 可能不是您想要的,因为这是一个昂贵的查询。至少创建一个非唯一索引

date, amount, account_id

对于这张桌子。这应该可以为您节省一些全表行扫描......另一种方法是执行类似的操作

Transaction.joins(<<eosql.strip)
  LEFT OUTER JOIN transactions t ON 
      transactions.id         != t.id AND
      transactions.date        = t.date AND
      transactions.amount      = t.amount
eosql

两种方式都很昂贵,内存方面。祝你好运。

于 2013-02-25T14:58:04.333 回答
1

如果您愿意将结果以多行形式返回给您,您可以尝试以下操作:

select account_id, amount, day, group_concat(id) 
  from purchases 
 group by account_id, amount, day having count(id) > 1;

这将返回一个结果集,其中每行包含给定帐户、日期和金额的重复项。

http://sqlfiddle.com/#!2/86e43/17

于 2013-02-26T02:15:26.303 回答
1

也许像

def similar
  table = self.class.arel_table
  conditions = %w[ date amount ].map { |field| table[field].eq send(field) }.map &:to_sql
  self.class.where "id != #{ id } AND #{ conditions.join ' AND ' }"
end
于 2013-02-25T23:55:51.930 回答