2012-04-19 3 views
0

많은 데이터를 가져와 계산을 실행하고 큰 테이블의 일부로 침을 뱉어내는 보고서를 생성해야합니다. 이렇게하는 것은 어렵지 않습니다. 그러나 기존 방법을 사용하여 1000 가지 SQL 쿼리를 생성하지 않도록하는 것이 훨씬 더 어렵습니다. 이 달의 시작 부분에 말을 계정의 균형을 얻기 위해 사용될 수ActiveRecord를 사용하여 효율적으로 보고서 생성

def balance_at(time=Time.now) 
    payments_out = self.payments.where("created_at <= ?",time).sum("amount") 
    payments_in = self.payments_on_account.where("created_at <= ?",time).sum("amount") 
    payments_in - payments_out 
end 

, 그리고 마지막 :

는 예를 들어이 같은 방법이있는 Account 클래스가있을 수 있습니다. 그것은 위대한 작품.

그러나 모든 테이블을 Account의 시작과 끝으로 균형을 유지하려면 바보가됩니다. 그래서 예를 들면 : (

Account.includes(:payments, :payments_on_account) 

내가 루비의 모든 순수하게이 위기 원한다면 내가 원하는 것 모든 데이터를 얻을 것이다,하지만 내 좋은 작은 방법은 balance_at 루비에 재정 숫자를 모두하지 않습니다 그것은 개별적인 경우에 대해 느릴 것이다).

나는과 같이 캐시되는 내용에 따라 루비를하지 뭔가 SQL 그것을 해결할 수 :

def balance_at(time=Time.now) 
    payments_out, payments_in = [payments, payments_on_account].map{|payments| 
    if payments.loaded? 
     payments.find_all{|p| p.created_at < time }.inject(0){|a,p| p.amount + a } 
    else 
     payments.where("created_at <= ?",time).sum("amount") 
    end 
    } 
    payments_in - payments_out 
end 

그러나, 읽을 끔찍한 또는 중 하나를 테스트하기 쉽지 않다.

어떻게 해결하겠습니까?

답변

1

저는보고가 필요한 몇 가지 프로젝트를 진행했습니다. 웹 애플리케이션 스택은보고를하기에 최적의 장소는 아니지만 오픈 소스보고 옵션은 상당히 제한적으로 보인다. 그러나 모든 조직이 SSRS 또는 Crystal을 사용할 수있는 것은 아니며 제 경험상 이러한 제품은 고통스럽고 필요 이상으로 많은 문제를 야기합니다.

나는 이것을 완료하기 위해보기를 사용하고 있습니다. SQL은 데이터를 그룹화하고 집계하기 위해 설계되었으며 루비보다이 물건을 다루기 위해 더 많이 갖추고 있습니다.그러나 대부분의 경우 조회수는 실시간으로 처리되기 때문에 여기서 성과를 얻지는 않습니다. 이상적으로 기본 구현을 얻은 후에는 cron 작업이나 데이터를 미리 계산할 수있는 방법을 설정할 수 있습니다. 보고서에 자주 액세스하고 하루 동안 액세스하려는 경우 전용보고 DB가 필요할 것입니다. 보고서에 실시간 데이터가 있어야하는 경우 복제를 설정해야합니다.

Ruby/Rails에서 SQL을 사용하는 것은 지저분한 일입니다. 그래서 나는 Skiima라고 불리는 보석을 썼는데, 그것은 당신이 당신의 프로젝트에서 가질지도 모르는 관계없는 SQL 객체들을 관리하도록 도와줍니다. 마이그레이션을로드하여 테스트하는 것이 더 쉬워집니다. 그 옆에서

http://github.com/dcunited001/skiima

이 내가 뭘했는지 있습니다 :

class AccountsReport < ActiveModel 
    attr_accessor :items 
    def initialize(attr = {}) 
    # read in params, set attrs 
    end 

    def execute 
    get_report_items 
    group_report_items 
    summarize_report_groups # if this needs to occur outside of sql 
    end 
end 

class AccoutsReportItem < ActiveRecord::Base 
    # you can hook into a view here, you will want the view to return an id col 
    set_table_name :view_accounts_report_items 
end 

# yay for arel and activerecord methods. 
# you can even set up relationships on these. use sparingly. 
# AccountsReportItem.where(:blah => 'balah') 
0

다른 도구와 달리 Rails 내부에 있다고 가정 할 때 가장 좋은 방법은 find_by_sql()을 사용하는 것입니다.

분명히 추한 일 이겠지만, READABLE이 될 것이며, 원시 SQL보다 더 추한 것은 아닙니다.

저는 "Ruby에서의 계산"이 보고서 용으로 훨씬 더 뛰어난 find_by_sql로 대체 된 수많은 Rails 응용 프로그램을 연구했습니다. 그것은 항상 조금 더러움을 느끼지만, 나는 또한 5m 보고서를 받아서 적절한 SQL을 사용하여 30 초 동안 실행하는 것을 좋아합니다.

+0

보고서와를 할 때 그 다음 범위로 계산의 각 유형을 넣어 수 있는지 궁금 X, Y, Z를 사용하면 해당 범위를 간단히 연결할 수 있습니다. 복잡한 쿼리를 통해 서로 간섭하기 시작하는 특정 시점에 도달 할 수 있는지 여부는 알 수 없습니다. 아마도 보고서의 각 열은'find_by_sql' 또는 범위와 관련이 있습니다. 그리고 쉽게 테스트 할 수 있으며 열 당 쿼리 가격에 충돌이 없도록 보장 할 수 있습니다. – Theozaurus

1

계정이 1000 개인 경우 첫 번째 질문은 모두 한꺼번에 표시해야합니까? 이것은 사용자에게 정말 유용한가요?

그렇지 않은 경우 첫 번째 방법을 계속할 수 있습니다. 페이지 당 계정 수를 허용 가능한 수준으로 제한하십시오. 함수 호출 당 두 개의 쿼리를 수행 할 것이지만 테스트 가능하고 신뢰할 수 있습니다.

보고서 인쇄용 페이지를 렌더링하는 경우 사용자에게 간단한 설명이 필요합니다.

더 빠른 솔루션에 대한 필요성을 이해하지만 때로는 더 빨리 사용자 친화적 인 것은 아닙니다.

+0

슬프게도 그것이 필요합니다. 유스 케이스의 종류는 회계 패키지에 보고서를 다운로드하는 것입니다. – Theozaurus

+0

백그라운드 스레드에서 보고서 생성을 실행하고 사용자에게 완료 사실을 알리는 가능성이 있습니까? 대규모 데이터 샘플을 실행하는 데 현재 얼마나 걸리나요? – apchester

+0

예, 가능합니다. 나는 최소한의 복잡성을 추가하면서 효율성의 관점에서 이것을 어떻게 해결할 것인가에 주로 관심이 있습니다. – Theozaurus

관련 문제