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:
- Problémy s Rails GitHub s uvedením „připojit“ a „alias“. Neštěstí.
- SO Question:Dotaz ActiveRecord s tabulkou aliasů jména
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!