sql >> データベース >  >> RDS >> PostgreSQL

重複レコードを返す(activerecord、postgres)

    SQLのような方法

    まず、Rails固有の構文が私たちをだまさないように、SQLの問題を解決しましょう。

    このSOの質問は、かなり明確な類似点です。重複を見つけるSQLテーブルの値

    KMからの回答(上から2番目、現時点ではチェックマークなし)は、重複するすべてのレコードをIDとともに返すという基準を満たしています。 KMを変更しました あなたのに一致するSQL テーブル...

    SELECT
      m.id, m.title
    FROM 
      movies m
    INNER JOIN (
      SELECT
        title, COUNT(*) AS CountOf
      FROM
        movies
      GROUP BY 
        title
      HAVING COUNT(*)>1
    ) dupes 
    ON
      m.title=dupes.title
    

    INNER JOIN ( )内の部分 基本的には、すでに生成したものです。重複したタイトルとカウントのグループ化されたテーブル。秘訣はJOINです 変更されていないmoviesにそれを追加する テーブル。重複のクエリで一致するものがない映画はすべて除外されます。

    Railsでこれを生成するのが難しいのはなぜですか?最も難しいのは、JOINだからです。 ing movies moviesへ 、テーブルエイリアス(m)を作成する必要があります およびdupes 上記の私のクエリで)。

    残念ながら、Railsはこれらのエイリアスを宣言するためのクリーンな方法を提供していません。いくつかの参考文献:

    幸い、SQLが手元にあるので、.find_by_sqlを使用できます。 メソッド...

    Movie.find_by_sql("SELECT m.id, m.title FROM movies m INNER JOIN (SELECT title, COUNT(*) FROM movies GROUP BY title HAVING COUNT(*)>1) dupes ON m.first=.first")
    

    Movie.find_by_sqlを呼び出しているため 、ActiveRecordは、手書きのSQLをMovieにバンドルできることを前提としています。 オブジェクト。マッサージも生成もしないため、エイリアスを作成できます。

    このアプローチには欠点があります。 ActiveRecordリレーションではなく配列を返します。つまり、他のスコープとチェーンすることはできません。また、find_by_sqlのドキュメントにある 方法 、私たちはさらに落胆します...

    Rails-y Way

    本当に、SQLは上記で何をしているのですか?複数回表示される名前のリストを取得しています。次に、そのリストを元のテーブルと照合します。それでは、Railsを使用してそれを実行しましょう。

    titles_with_multiple = Movie.group(:title).having("count(title) > 1").count.keys
    
    Movie.where(title: titles_with_multiple)
    

    .keysと呼びます 最初のクエリがハッシュを返すためです。キーは私たちのタイトルです。 where() メソッドは配列を取ることができ、タイトルの配列を渡しました。勝者。

    Rubyの1行は2行よりもエレガントであると言えるでしょう。そして、Rubyのその1行にSQLの不敬虔な文字列が埋め込まれている場合、それは本当にどれほどエレガントですか?

    これがお役に立てば幸いです!



    1. チェックボックスをオフにすると、null値が返されます

    2. SQLServerで文字列の左または右から特定の数の文字を選択する方法

    3. SELECTステートメントでto_date例外を処理して、それらの行を無視するにはどうすればよいですか?

    4. OPTIONを使用した無限ループCTE(maxrecursion 0)