복붙노트

[SQL] 어떻게 서로 다른 값을 가진 테이블을 조인을 사용 값을 얻으려면?

SQL

어떻게 서로 다른 값을 가진 테이블을 조인을 사용 값을 얻으려면?

나는 제품, 사용자와 product_click 모델을 가지고있다. product_click에서, 나는 기록, 제품 횟수를 사용자가 클릭을 유지하고있어 열 수 있습니다.

나는 또한 시도

Product.sort_by{ |r|  r.product_clicks.where(user_id: user.id).first.try(:count).to_i

어떤 욕망 결과를 제공하지만 실행에 쿼리를 많이 생성.

product_click.rb

belongs_to :product
  belongs_to :user

product.rb

has_many :product_clicks, dependent: :destroy

user.rb

has_many :product_clicks, dependent: :destroy

개요

create_table "product_clicks", force: :cascade do |t|
    t.bigint "product_id"
    t.bigint "user_id"
    t.bigint "count", default: 0
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

컨트롤러에서

Product.left_outer_joins(:product_clicks).order("count DESC NULLS LAST")

지금은 일이 뭔가를 찾고 있어요.

그러나 여기서 내가 할 수없는 카운트가있는 특정 사용자의 여부를 확인 할 수 있습니다. 내가 추가 해요 만약

Product.left_outer_joins(:product_clicks).where(resource_clicks: { user_id: user.id }).order("count DESC NULLS LAST")

그 다음은 사용자가 클릭 한 제품하지만 (내가 클릭하지)가 '전무'사람을 게재합니다.

나는 또한이 시도

Product.left_outer_joins(:product_clicks).where(product_clicks: { user_id: [user.id, nil] }).order("count DESC NULLS LAST")

그러나 저를주는 것은 내가 클릭 모든 모든 다른 클릭하지 않는 아무도. 누군가가 클릭하는 경우 난 후 나에게 표시되지 않았다.

해결법

  1. ==============================

    1.나는 다른 방법을 생각하고 있지만, 하나의 직선 방법은 2 단계의 솔루션이 될 것입니다.

    나는 다른 방법을 생각하고 있지만, 하나의 직선 방법은 2 단계의 솔루션이 될 것입니다.

    product_ids = ProductClick.where(user_id: user.id).order('count desc').pluck(:product_id)
    
    products = Product.where(id: product_ids)
    

    그것은 확실히 당신의 시간을 개선하고 (N + 1) 귀하의 요청에보다 더 나은 것입니다.

    미리로드를 사용하여

    Product.includes(:product_clicks).where('product_clicks.user_id' => user.id).order('product_clicks.count desc')
    

    위의 쿼리는하지만, 내부적 어쨌든이 쿼리를 공격 할 수 있습니다, 같은 방식으로 발생한다.

    HAVING 절을 사용 - 권장

    Product.includes(:product_clicks).having('product_clicks.user_id' => user.id).order('product_clicks.count desc')
    

    업데이트 - 사용 또는

    Product.includes(:product_clicks).where('product_clicks.user_id' => user.id)
           .order('product_clicks.count desc')
           .or(
            Product.includes(:product_clicks)
                   .where('product_clicks.user_id' => user.id)
                   .where(product_clicks: { id: nil })
           )
    
  2. from https://stackoverflow.com/questions/56669484/how-to-get-value-using-join-table-with-different-values by cc-by-sa and MIT license