게 찾을 수 있는 방법에 관련된 테이블에 가장 오래된 기록을 필터에 의해 그것의 하나의 특?

0

질문

내 모델 Subscriptionhas_many Versions.

A Versionstatus, plan_idauthorized_at 날짜입니다.

어떤 변경사항 Subscription 에서 오 Version 수정 업데이트 그의 부모로 Subscription.

의 목표는 각 구독 Version 가장 오래된 authorized_at 날짜 WHEREversions.plan_idsubscriptions.plan_id (다른 단어에서 나는 권한이 필요합 날짜 Versionplan_id 변경 현재 Subscriptionko plan_id).

이것은 쿼리러 왔습니다. 나에 오류가 집계 기능 syntax:

syntax error at or near "MIN" LINE 3: MIN (authorized_at) from versions ^

쿼리:

select subscriptions.id,
MIN (authorized_at) from versions
where versions.plan_id = subscriptions.plan_id
) as current_version
from subscriptions
join versions on subscriptions.id = versions.subscription_id
where versions.status = 'processed'

는 확실하지 않으면 내가 그룹화하여 버전 plan_id 다음에서 각 그룹이다. 나는 종류의 손실됩니다.

database postgresql ruby ruby-on-rails
2021-11-23 14:26:06
3

최고의 응답

1

당신이 사용할 수 있는 측면 하위 할 수 있는 최고의로 설명 될 foreach 루프에서 SQL. 그들은 매우 성능이 뛰어 방법으로 열을 선택하려면에서 상관된 레코드 또는 골재 그룹에서의 관련 기록합니다.

각 행에 대해 구독의 DB 로 선택하는 단 하나 줄 버전에서 주문 authorized_at:

SELECT "subscriptions".*,
       "latest_version"."authorized_at" AS current_version,
       "latest_version"."id" AS current_version_id -- could be very useful
FROM   "subscriptions" 
LATERAL
  (
     SELECT   "versions"."authorized_at", "versions"."id"
     FROM     "versions"
     WHERE    "versions"."subscription_id" = "subscriptions"."id" -- lateral reference
     AND      "versions"."plan_id" = "subscriptions"."plan_id"
     AND      "versions"."status" = 'processed'
     ORDER BY "versions"."authorized_at" ASC
     LIMIT 1
  ) latest_version ON TRUE

성 측면에 조인 ActiveRecord 중 하나를 수행 할 수 있습 SQL 문자열이나 Arel:

class Subscription < ApplicationRecord
  # Performs a lateral join and selects the 
  # authorized_at of the latest version 
  def self.with_current_version
    lateral = Version.arel_table.then do |v|
      v.project(
        v[:authorized_at],
        v[:id] # optional
      ).where(
        v[:subscription_id].eq(arel_table[:id])
          .and(v[:plan_id].eq(arel_table[:plan_id]) )
          .and(v[:status].eq('processed'))
      )
      .order(v[:authorized_at].asc)
      .take(1) # limit 1
      .lateral('latest_version ON TRUE')
    end
    lv = Arel::Table.new(:latest_version) # just a table alias
    select(
      *where(nil).arel.projections, # selects everything previously selected
      lv[:authorized_at].as("current_version"),
      lv[:id].as("current_version_id") # optional
    ).joins(lateral.to_sql)
  end
end

는 경우에 당신을 선택하려면 idcurrent_version 열를 사용하는 것을 고려해야 합니다 뽑을 선택하는 대신 데이터베이스는 모델이 되지 않습니다 제대로 수분을 유지합니다.

2021-11-23 16:49:48
1

당신이 사용할 수 있는 DISTINCT ON 행을 필터링하기 위해,그리고 계속 하나 하나 구독당 첫 번째 그룹별로 하나에 따라 ORDER BY 절입니다.

예를 들어:

select distinct on (s.id) s.id, v.authorized_at
from subscription s
join versions v on v.subscription_id = s.id and v.plan_id = s.plan_id
where v.status = 'processed'
order by s.id, v.authorized_at
2021-11-23 16:40:51

감사합니다. 쿼리에서 작동하는 것 같 콘솔,하지만 사용하려고 시도하면 그것을 내망으로 모델의 범위를 나 ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: syntax error at or near "WHERE" LINE 6: ...s.id, v.authorized_at WHERE "sub...
pinkfloyd90

@pinkfloyd90 내가 전문가에 ActiveRecord,하지만 어쩌면 그것은 작동하지 않기 때문에 넣은 아마 업데이트할 수 있습니다.
The Impaler
0

아래 코드를 제공할 것입 versions 는 버전의 plan_id 과 같 구독 plan_id.

@versions = Version.joins("LEFT JOIN subscriptions ON subscriptions.plan_id = versions.plan_id")

필터를 레코드로 버전의 status

@versions = Version.joins("LEFT JOIN subscriptions ON subscriptions.plan_id = versions.plan_id").where(status: "processed")

필터를 레코드로 버전의 status 및 순서 authorized_at 오름차순으로 정렬됩니다.

@versions = Version.joins("LEFT JOIN subscriptions ON subscriptions.plan_id = versions.plan_id").where(status: "processed").order(:authorized_at)

필터를 레코드로 버전의 status 및 순서 authorized_at 에 decending 다.

@versions = Version.joins("LEFT JOIN subscriptions ON subscriptions.plan_id = versions.plan_id").where(status: "processed").order(authorized_at: :desc)

이 작품을 위해 당신!

2021-11-23 14:33:48

나는 당신이 필요하다고 생각하여 가입하세에 subscriptions.id = versions.subscription_id 또는 당신을 얻을 것이 버전에서는 결과에 속하지 않는 것입니다. 당신은 또한이 없도에 감동의 핵심 질문을 선택하는 응집합니다.
max

다른 언어로

이 페이지는 다른 언어로되어 있습니다

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................