PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Zwróć zduplikowane rekordy (activerecord, postgres)

Sposób SQL-y

Najpierw po prostu rozwiążmy problem w SQL, aby składnia specyficzna dla Railsów nas nie oszukała.

To pytanie SO jest dość wyraźną paralelą:Znajdowanie duplikatu wartości w tabeli SQL

Odpowiedź od KM (druga od góry, obecnie niezaznaczona) spełnia Twoje kryteria zwrotu wszystkich zduplikowanych rekordów wraz z ich identyfikatorami. Zmodyfikowałem KM SQL pasujący do Twojego stół...

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

Część wewnątrz INNER JOIN ( ) jest zasadniczo tym, co już wygenerowałeś. Zgrupowana tabela z powielonymi tytułami i liczbami. Sztuczka to JOIN do niezmodyfikowanych movies tabeli, która wyklucza wszystkie filmy, które nie mają dopasowań w zapytaniu duplikatów.

Dlaczego tak trudno to wygenerować w Railsach? Najtrudniejsze jest to, że jesteśmy JOIN ing movies do movies , musimy utworzyć aliasy tabel (m i dupes w moim zapytaniu powyżej).

Niestety, it Rails nie zapewnia żadnych czystych sposobów deklarowania tych aliasów. Niektóre referencje:

Na szczęście, ponieważ mamy pod ręką SQL, możemy użyć .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")

Ponieważ dzwonimy do Movie.find_by_sql , ActiveRecord zakłada, że ​​nasz ręcznie napisany kod SQL można umieścić w pakiecie Movie przedmioty. Nie masuje ani nie generuje niczego, co pozwala nam tworzyć nasze aliasy.

Takie podejście ma swoje wady. Zwraca tablicę, a nie relację ActiveRecord, co oznacza, że ​​nie można jej łączyć z innymi zakresami. Oraz w dokumentacji find_by_sql metoda , dostajemy dodatkowe zniechęcenie...

Sposób Rails-y

Naprawdę, co robi SQL powyżej? Pobiera listę nazwisk, które pojawiają się więcej niż raz. Następnie dopasowuje tę listę do oryginalnej tabeli. Zróbmy to po prostu za pomocą Railsów.

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

Movie.where(title: titles_with_multiple)

Nazywamy .keys ponieważ pierwsze zapytanie zwraca hash. Kluczami są nasze tytuły. where() Metoda może przyjąć tablicę, a my przekazaliśmy jej tablicę tytułów. Zwycięzca.

Można argumentować, że jedna linia Ruby jest bardziej elegancka niż dwie. A jeśli ta jedna linijka Rubiego ma osadzony w sobie bezbożny ciąg SQL, jak naprawdę jest elegancki?

Mam nadzieję, że to pomoże!



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Błąd w LINQ (kolumna nie istnieje) podczas korzystania z Entity Framework

  2. Kombinacje zapytań z zagnieżdżoną tablicą rekordów w typie danych JSON

  3. PostgreSQL, rekonfiguracja istniejącej tabeli, zmiana klucza podstawowego na type=serial

  4. Nadchodzi Postgresql JSONB. Czego teraz użyć? Hsklep? JSON? EAV?

  5. Wygeneruj losową liczbę z zakresu 1 - 10