use*_*502 3 greatest-n-per-group laravel eloquent laravel-5
使用 Eloquent,试图找到一种方法来获取按以下方式分组的每一行的最新行:exchange、base、quote
数据
exchange base quote price value created_at
bittrex BTC USD 10000 10000 2018-01-05
bittrex BTC USD 9000 9000 2018-01-01
poloniex BTC USD 10001 10001 2018-01-05
poloniex BTC USD 9000 9000 2018-01-01
binance BTC USD 10002 10002 2018-01-05
binance BTC USD 9000 9000 2018-01-01
binance ETH USD 800 800 2018-01-05
binance ETH USD 700 700 2018-01-01
Run Code Online (Sandbox Code Playgroud)
结果:
bittrex BTC USD 10000 10000 2018-01-05
poloniex BTC USD 10001 10001 2018-01-05
binance BTC USD 10002 10002 2018-01-05
binance ETH USD 800 800 2018-01-05
Run Code Online (Sandbox Code Playgroud)
更新
我选择了@Cryode 解决方案,原始 SQL 而不是 Eloquent(如果有人可以提出一个 Eloquent 查询来复制下面查询的结果,请随时发布)。
我还更改了表的结构以添加id(增量)作为主键。我还添加了以下索引$table->index(['exchange', 'base', 'quote', 'created_at']);
这是解决方案:
$currencies = DB::select('SELECT *
FROM (
SELECT DISTINCT exchange, base, quote
FROM tickers
) AS t1
JOIN tickers
ON tickers.id =
(
SELECT id
FROM tickers AS t2
WHERE t2.exchange = t1.exchange
AND t2.base = t1.base
AND t2.quote = t1.quote
ORDER BY created_at DESC
LIMIT 1
)
');
Run Code Online (Sandbox Code Playgroud)
谢谢
让我们首先确定这个 SQL 查询实际上是什么样的。
这个 DBA 回答提供了对“greatest-n-per-group”问题以及 PostgreSQL 和 MySQL 示例的一些深刻见解。受此答案的启发,这是我为您的单表提出的建议(假设 MySQL 作为您的数据库):
SELECT ticker.*
FROM (
SELECT DISTINCT exchange, base, quote
FROM ticker
) AS exchanges
JOIN ticker
ON ticker.id =
(
SELECT id
FROM ticker
WHERE ticker.exchange = exchanges.exchange
AND ticker.base = exchanges.base
AND ticker.quote = exchanges.quote
ORDER BY created_at DESC
LIMIT 1
);
Run Code Online (Sandbox Code Playgroud)
哦亲爱的。将其引入 Laravel-speak 看起来并不容易。
就个人而言,我什至不会尝试。复杂的 SQL 查询只是因为它们利用您的数据库进行报告、数据收集等。尝试将其推送到查询构建器中是乏味的,并且可能几乎没有任何好处。
也就是说,如果你想使用 Laravel 的查询构建器和 Eloquent 以简单的方式获得相同的结果,这里有一个选项:
// Get the unique sets of tickers we need to fetch.
$exchanges = DB::table('ticker')
->select('exchange, base, quote')
->distinct()
->get();
// Create an empty collection to hold our latest ticker rows,
// because we're going to fetch them one at a time. This could be
// an array or however you want to hold the results.
$latest = new Collection();
foreach ($exchanges as $exchange) {
$latest->add(
// Find each group's latest row using Eloquent + standard modifiers.
Ticker::where([
'exchange' => $exchange->exchange,
'base' => $exchange->base,
'quote' => $exchange->quote,
])
->latest()
->first()
);
}
Run Code Online (Sandbox Code Playgroud)
优点:您可以使用查询构建器和 Eloquent 抽象;允许您维护您的 Ticker 模型,该模型可能在请求期间需要额外的逻辑。
缺点:需要多次查询。
另一种选择是使用封装复杂查询的MySQL 视图,并创建一个单独的 Eloquent 模型,该模型将从该视图中获取。这样,您的应用程序代码就可以像TickerLatest::all().
| 归档时间: |
|
| 查看次数: |
4519 次 |
| 最近记录: |