PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Trả lại các bản ghi trùng lặp (activerecord, postgres)

Cách sử dụng SQL-y

Đầu tiên, hãy giải quyết vấn đề trong SQL để cú pháp cụ thể của Rails không đánh lừa chúng ta.

Câu hỏi SO này là một song song khá rõ ràng: Tìm trùng lặp giá trị trong Bảng SQL

Câu trả lời từ KM (thứ hai từ trên cùng, không được đánh dấu, tại thời điểm này) đáp ứng tiêu chí của bạn là trả lại tất cả các bản ghi trùng lặp cùng với ID của chúng. Tôi đã sửa đổi KM's SQL để khớp với của bạn bảng ...

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

Phần bên trong INNER JOIN ( ) về cơ bản là những gì bạn đã tạo. Một bảng được nhóm các tiêu đề và số lượng trùng lặp. Bí quyết là JOIN nhập nó vào movies chưa sửa đổi bảng này sẽ loại trừ bất kỳ phim nào không trùng khớp trong truy vấn lừa đảo.

Tại sao điều này rất khó tạo trong Rails? Phần khó nhất là vì chúng ta đang JOIN ing movies tới movies , chúng ta phải tạo bí danh bảng (mdupes trong truy vấn của tôi ở trên).

Đáng buồn thay, nó Rails không cung cấp bất kỳ cách khai báo rõ ràng nào về các bí danh này. Một số tài liệu tham khảo:

May mắn thay, vì chúng tôi đã có SQL trong tay, chúng tôi có thể sử dụng .find_by_sql phương pháp ...

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

Vì chúng tôi đang gọi Movie.find_by_sql , ActiveRecord giả sử SQL viết tay của chúng ta có thể được đóng gói vào Movie các đối tượng. Nó không xoa bóp hay tạo ra bất cứ thứ gì, điều này cho phép chúng tôi tạo bí danh của mình.

Cách tiếp cận này có những thiếu sót của nó. Nó trả về một mảng chứ không phải ActiveRecord Relation, có nghĩa là nó không thể được xâu chuỗi với các phạm vi khác. Và, trong tài liệu cho find_by_sql phương pháp , chúng tôi càng thêm chán nản ...

Một cách Rails-y

Thực sự, SQL đang làm gì ở trên? Nó nhận được một danh sách các tên xuất hiện nhiều hơn một lần. Sau đó, nó khớp danh sách đó với bảng gốc. Vì vậy, hãy làm điều đó bằng cách sử dụng Rails.

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

Movie.where(title: titles_with_multiple)

Chúng tôi gọi .keys bởi vì truy vấn đầu tiên trả về một hàm băm. Chìa khóa là chức danh của chúng tôi. where() phương thức có thể nhận một mảng và chúng tôi đã cung cấp cho nó một mảng tiêu đề. Người chiến thắng.

Bạn có thể tranh luận rằng một dòng của Ruby thanh lịch hơn hai dòng. Và nếu một dòng Ruby đó có một chuỗi SQL không ổn định được nhúng bên trong nó, thì nó thực sự thanh lịch đến mức nào?

Hy vọng điều này sẽ hữu ích!



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thu gọn các hàng thành một cột

  2. plpgsql - sử dụng tên bảng động trong câu lệnh khai báo

  3. Triển khai Postgres Sql trong Apache Airflow

  4. Java JDBC bỏ qua setFetchSize?

  5. Tạo cơ sở dữ liệu Postgres bằng python