我在PostGres 9.5中使用Rails 5。我有一张跟踪价格的表......
Table "public.crypto_prices"
Column | Type | Modifiers
--------------------+-----------------------------+------------------------------------------------------------
id | integer | not null default nextval('crypto_prices_id_seq'::regclass)
crypto_currency_id | integer |
market_cap_usd | bigint |
total_supply | bigint |
last_updated | timestamp without time zone |
created_at | timestamp without time zone | not null
updated_at | timestamp without time zone | not null
我想获得所选货币的每种货币的最新价格(last_updated
最大)。我可以找到与某些货币相关的所有价格,如此
current_prices = CryptoPrice.where(crypto_currency_id: CryptoIndexCurrency.all.pluck(:crypto_currency_id).uniq)
然后我可以按货币对数组进行排序,循环遍历每个数组,直到找到last_updated
值最大的那个,但是我怎么能写一个每个货币只返回一行的查找器最大的last_updated
日期?
编辑:尝试过Owl Max的建议
ids = CryptoIndexCurrency.all.pluck(:crypto_currency_id).uniq
crypto_price_ids = CryptoPrice.where(crypto_currency_id: ids).group(:crypto_currency_id).maximum(:last_updated).keys
puts "price ids: #{crypto_price_ids.length}"
@crypto_prices = CryptoPrice.where(crypto_currency_id: crypto_price_ids)
puts "ids: #{@crypto_prices.size}"
虽然第一个" put"只显示" 12"第二个结果显示超过38,000个结果。它应该只返回12个结果,每个货币一个。
答案 0 :(得分:1)
我们可以编写一个查找器,每个货币只返回一行,其中last_updated日期最长,如
current_prices = CryptoPrice.where(crypto_currency_id: CryptoIndexCurrency.all.pluck(:crypto_currency_id).uniq).select("*, id as crypto_price_id, MAX(last_updated) as last_updated").group(:crypto_currency_id)
我希望这会让你更接近你的目标。谢谢。
答案 1 :(得分:0)
使用此代码,您可以从特定表中获取最新更新的行。
CryptoPrice.order(:updated_at).pluck(:updated_at).last
这应该对你有帮助。
答案 2 :(得分:0)
由于or
查询方法
specific_ids = CryptoIndexCurrency.distinct.pluck(:crypto_currency_id)
hash = CryptoPrice.where(crypto_currency_id: specific_ids)
.group(:crypto_currency_id)
.maximum(:last_updated)
hash.each_with_index do |(k, v), i|
if i.zero?
res = CryptoPrice.where(crypto_currency_id: k, last_updated: v)
else
res.or(CryptoPrice.where(crypto_currency_id: k, last_updated: v))
end
end
<强>解释强>:
您可以使用group
重新组合表格中每个CryptoPrice
礼物的所有CryptoIndexCurrency
个对象。
然后使用maximum
(感谢@artgb)获取最大值last_updated
。这将输出Hash
,其中包含键:crypto_currency_id
和值
last_updated
。
最后,您可以使用keys
仅获得Array
crypto_currency_id
。
CryptoPrice.group(:crypto_currency_id).maximum(:last_updated)
=> => {2285=>2017-06-06 09:06:35 UTC,
2284=>2017-05-18 15:51:05 UTC,
2267=>2016-03-22 08:02:53 UTC}
此解决方案的问题在于,您无需获取整个记录即可获得每行的最长日期。
要获取记录,您可以成对地对哈希进行循环。使用crypto_currency_id
和last_updated
。它是hacky但是我发现的唯一解决方案。
答案 3 :(得分:0)
在一个语句/查询中,这在Rails中目前并不容易。如果您不介意使用多个语句/查询,那么这是您的解决方案:
cc_ids = CryptoIndexCurrency.distinct.pluck(:crypto_currency_id)
result = cc_ids.map do |cc_id|
max_last_updated = CryptoPrice.where(crypto_currency_id: cc_id).maximum(:last_updated)
CryptoPrice.find_by(crypto_currency_id: cc_id, last_updated: max_last_updated)
end
您正在寻找map
方法的结果。这会为每个crypto_currency_id
和1个查询生成2个查询,以请求crypto_currency_id
。
如果您想使用一个查询执行此操作,则需要使用OVER (PARTITION BY ...)
。有关此内容的更多信息,请访问以下链接:
但在这种情况下,您必须编写一些SQL。
编辑1:
如果你想要一个不错的Hash
结果运行:
cc_ids.zip(result).to_h
编辑2:
如果您希望将查询量减半,可以将max_last_updated
中的find_by
查询推送为子查询,如下所示:
cc_ids = CryptoIndexCurrency.distinct.pluck(:crypto_currency_id)
result = cc_ids.map do |cc_id|
CryptoPrice.find_by(<<~SQL.squish)
crypto_currency_id = #{cc_id} AND last_updated = (
SELECT MAX(last_updated)
FROM crypto_prices
WHERE crypto_currency_id = #{cc_id})
SQL
end
这会为每个crypto_currency_id
和1个查询生成1个查询,以请求crypto_currency_id
。