programing

활성 레코드, 레일 및 포스트그레스를 사용하여 여러 중복 필드가 있는 행 찾기

batch 2023. 5. 1. 20:40
반응형

활성 레코드, 레일 및 포스트그레스를 사용하여 여러 중복 필드가 있는 행 찾기

Postgres 및 Active record를 사용하여 여러 열의 중복 값이 있는 레코드를 찾는 가장 좋은 방법은 무엇입니까?

여기서 이 솔루션을 찾았습니다.

User.find(:all, :group => [:first, :email], :having => "count(*) > 1" )

하지만 그것은 우체국에서는 작동하지 않는 것 같습니다.다음 오류가 발생합니다.

PG::GroupingError: ERROR: "parts.id " 열이 GROUP BY 절에 나타나거나 집계 함수에서 사용되어야 합니다.

테스트 및 작업 버전

User.select(:first,:email).group(:first,:email).having("count(*) > 1")

또한, 이것은 약간 관련이 없지만 편리합니다.각 조합이 발견된 횟수를 확인하려면 마지막에 .size를 입력합니다.

User.select(:first,:email).group(:first,:email).having("count(*) > 1").size

그러면 다음과 같은 결과가 반환됩니다.

{[nil, nil]=>512,
 ["Joe", "test@test.com"]=>23,
 ["Jim", "email2@gmail.com"]=>36,
 ["John", "email3@gmail.com"]=>21}

저는 그것이 꽤 멋지다고 생각했고 전에 그것을 본 적이 없었습니다.

타린에게 공을 인정합니다, 이것은 그녀의 대답을 수정한 것일 뿐입니다.

이 오류는 POSTGRES에서 그룹화 열을 SELECT 절에 넣어야 하기 때문에 발생합니다.

시도:

User.select(:first,:email).group(:first,:email).having("count(*) > 1").all

(참고: 테스트되지 않음, 조정이 필요할 수 있음)

ID 열을 제거하도록 편집됨

전체 모델이 필요한 경우 다음을 시도하십시오(@newUserName 기준).답은 이렇습니다).

User.where(email: User.select(:email).group(:email).having("count(*) > 1").select(:email))

행의 전자 메일 주소가 고유하지 않은 행을 반환합니다.

여러 속성에 대해 이 작업을 수행할 방법을 모르겠습니다.

Postgre를 사용하는 경우 단일 쿼리로 모든 중복 항목 가져오기SQL:

def duplicated_users
  duplicated_ids = User
    .group(:first, :email)
    .having("COUNT(*) > 1")
    .select('unnest((array_agg("id"))[2:])')

  User.where(id: duplicated_ids)
end

irb> duplicated_users

나는 제대로 하려고 애썼습니다.User승인된 답변을 통해 반환된 모델입니다.방법:

User
  .group(:first, :email)
  .having("COUNT(*) > 1")
  .select('array_agg("id") as ids')
  .map(&:ids)
  .map { |group| group.map { |id| User.find(id) } }

이렇게 하면 다음과 같이 상호 작용할 수 있는 적절한 모델이 반환됩니다.

[
  [User#1, User#2],
  [User#35, User#59],
]

원시 SQL에서 잘 작동:

# select array_agg(id) from attendances group by event_id, user_id having count(*) > 1;
   array_agg   
---------------
 {3712,3711}
 {8762,8763}
 {7421,7420}
 {13478,13477}
 {15494,15493}

위의 @itsnikolay 답변을 기반으로 하지만 ActiveRecord 범위를 전달할 수 있는 방법을 만듭니다.

#pass in a scope, and list of columns to group by
# map(&:dupe_ids) to see your list 
def duplicate_row_ids(ar_scope, attrs)
  ar_scope
    .group(attrs)
    .having("COUNT(*) > 1")
    .select('array_agg("id") as dupe_ids')      
end

 #initial scope to narrow where you want to look for dupes
 ar_scope = ProductReviews.where( product_id: "194e676b-741e-4143-a0ce-10cf268290bb", status: "Rejected")
#pass the scope, and list of columns to group by
results = duplicate_row_ids(ar_scope, [:nickname, :overall_rating, :source, :product_id, :headline, :status])
#get your list
id_pairs = results.map &:dupe_ids
#each entry is an array
#then go through your pairs and take action

@newUserName의 위 답변을 기반으로 합니다.여기서 나는 각각의 숫자를 보여주는 올바른 방법이라고 생각합니다.

res = User.select('first, email, count(1)').group(:first,:email).having('count(1) > 1')

res.each {|r| puts r.attributes } ; nil

언급URL : https://stackoverflow.com/questions/21669202/find-rows-with-multiple-duplicate-fields-with-active-record-rails-postgres

반응형