sql >> Databáze >  >> RDS >> PostgreSQL

Vrátit duplicitní záznamy (activerecord, postgres)

Způsob SQL-y

Nejprve vyřešme problém v SQL, aby nás syntaxe specifická pro Rails neoklamala.

Tato otázka SO je docela jasná paralela:Hledání duplikátu hodnoty v tabulce SQL

Odpověď z KM (druhá shora, v tuto chvíli nezaškrtnutá) splňuje vaše kritéria pro vrácení všech duplicitních záznamů spolu s jejich ID. Upravil jsem KM SQL, aby odpovídal vašemu tabulka...

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

Část uvnitř INNER JOIN ( ) je v podstatě to, co jste již vytvořili. Seskupená tabulka duplicitních titulů a počtů. Trik je JOIN jeho přidání do neupravených movies tabulka, která vyloučí všechny filmy, které nemají shody v dotazu dupes.

Proč je to tak těžké generovat v Rails? Nejsložitější na tom je, protože jsme JOIN ing movies na movies , musíme vytvořit aliasy tabulek (m a dupes v mém dotazu výše).

Je smutné, že it Rails neposkytuje žádné čisté způsoby, jak tyto aliasy deklarovat. Některé odkazy:

Naštěstí, protože máme SQL v ruce, můžeme použít .find_by_sql metoda...

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")

Protože voláme Movie.find_by_sql , ActiveRecord předpokládá, že naše ručně psané SQL lze sbalit do Movie objektů. Nic nemasíruje ani negeneruje, což nám umožňuje vytvářet aliasy.

Tento přístup má své nedostatky. Vrací pole a ne vztah ActiveRecord, což znamená, že jej nelze zřetězit s jinými obory. A v dokumentaci pro find_by_sql metoda , dostáváme další odrazení...

A Rails-y Way

Opravdu, co dělá SQL výše? Získává seznam jmen, která se objevují více než jednou. Potom tento seznam porovnává s původní tabulkou. Udělejme to tedy pomocí Rails.

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

Movie.where(title: titles_with_multiple)

Říkáme .keys protože první dotaz vrací hash. Klíče jsou naše tituly. where() metoda může mít pole a my jsme jí předali pole názvů. Vítěz.

Můžete namítnout, že jedna řada Ruby je elegantnější než dvě. A pokud má tento řádek Ruby vložený bezbožný řetězec SQL, jak elegantní je ve skutečnosti?

Doufám, že to pomůže!



  1. inno db úrovně izolace a zamykání

  2. odkazování na více cizích klíčů php mysql

  3. Použití OraclePreparedStatement s připojením DBCP

  4. Jak odstranit omezení cizího klíče v SQL