![](/img/trans.png)
[英]rails 4 find_by_sql not returning the same results as phpPgAdmin
[英]Rails 4, PostgreSQL: convert results of find_by_sql aggregate functions into OpenStruct
在報告/指標頁面上工作時,我需要盡最大可能優化查詢,因此我使用find_by_sql來提高效率。
我的查詢之一是做一些匯總函數,在其中我返回一個計數和一些和。 我將此查詢的結果分配給模型的實例變量。
我有有效的代碼,但是代碼使我感到恐懼。 我已經閱讀了有關使用方法的官方Ruby / Rails文檔,但我仍然認為我的操作存在問題。
def initialize(args)
@loans_count = stats.loans_count
@total_fees_in_cents = stats.total_fees_in_cents
@total_amount_in_cents = stats.total_amount_in_cents
end
def stats
@stats ||= find_stats
end
def find_stats
if single_year?
loans = Loan.find_by_sql(["SELECT count(*) as loans_count, sum(amount) as total_amount_in_cents, sum(fee) as total_fees_in_cents FROM loans WHERE account_id = ? AND year = ? LIMIT 1", @account_id, @year]).first
else
loans = Loan.find_by_sql(["SELECT count(*) as loans_count, sum(amount) as total_amount_in_cents, sum(fee) as total_fees_in_cents FROM loans WHERE account_id = ? LIMIT 1", @account_id]).first
end
# Store results in OpenStruct for ease of access later on
OpenStruct.new(
loans_count: loans.loans_count || 0,
total_fees_in_cents: loans.total_fees_in_cents || 0,
total_amount_in_cents: loans.total_amount_in_cents || 0
)
end
關注
find_by_sql
應該返回一個數組; 即使找不到匹配項(空值,但有效行),SQL仍將始終返回一行。 但是,有一個原因我不應該在返回的數組上調用.first
嗎? 在某些我沒想到的情況下,我擔心會碰到[].first => nil
。 stats
方法“緩存”結果的方法是僅查詢數據庫1次的合適方法嗎? 似乎很多代碼和方法只是為了獲取一些匯總數據。 擔,
有兩種方法可以解決此問題...
我想我可以在這里用一個答案(^ _-)解決這兩個問題,關鍵是解決您的恐懼。
您主要擔心整個[].first => nil
。 其次,您擔心數據庫效率。 第三,您想使它整潔並重構(對您有好處!)。
您的答案...讓PostgreSQL為您完成這項工作,並強制它每次都返回一個非零的答案。 得到它?
OpenStruct
因為SQL查詢中的標簽相同。 COALESCE()
將null強制為零。 LIMIT 1
。 讓我們重寫代碼:
def initialize(args)
@loans_count = stats.loans_count
@total_fees_in_cents = stats.total_fees_in_cents
@total_amount_in_cents = stats.total_amount_in_cents
end
def stats
loans = Loan.select("count(*) as loans_count, COALESCE(sum(amount), 0) as total_amount_in_cents, COALESCE(sum(fee), 0) as total_fees_in_cents").where(account_id: @account_id)
loans = loans.where(year: @year) if single_year?
loans.first
end
我個人認為您過於擔心數據庫效率問題。 您始終可以查看您的開發/生產日志,以讀取實際輸出到PSQL服務器的內容,但是我敢肯定,這與您在此處所做的相同。
另外,如果我沒記錯的話,直到查詢到數據時,數據庫查詢才真正執行。 在這段時間內,ActiveRecord只是在准備QUERY字符串。
.to_i
會將您的null轉換為零。
讓我們重寫代碼:
def initialize(args)
stats = Loan.where(account_id: @account_id)
stats = stats.where(year: @year) if single_year?
stats.first
@loans_count = stats.count
@total_fees_in_cents = stats.sum(:fee).to_i
@total_amount_in_cents = stats.sum(:amount).to_i
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.