使用雄辩,试图找到一种方法,以获得每一行的最新行分组: exchange,base,引号
数据
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结果:
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更新
我使用了@Cryode解决方案,它是原始SQL,而不是雄辩的SQL(如果有人可以提出一个雄辩的查询来复制下面查询的结果,请随意发布)。
我还更改了表的结构,以添加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
)
');谢谢
发布于 2018-02-25 06:50:52
让我们首先确定这个SQL查询的实际外观。
这个DBA的回答为“每个组中最大的n个组”问题提供了一些很好的见解,以及PostgreSQL和MySQL示例。在这个答案的启发下,我为您的单个表(假设MySQL为您的DB)提供了如下内容:
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
);哦,亲爱的。把它讲给拉勒维尔听看来不容易。
就我个人而言,我甚至不会尝试。复杂的SQL查询只是因为它们利用您的数据库来进行报告、数据收集等。试图将其推入查询生成器是很乏味的,而且可能没有什么好处。
尽管如此,如果您希望使用Laravel的查询生成器和雄辩器以简单的方式获得相同的结果,下面是一个选项:
// 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()
);
}优点:您可以使用查询生成器和雄辩的抽象;允许您维护您的Ticker模型,该模型在请求期间可能需要额外的逻辑。
缺点:需要多个查询。
另一种选择可以是使用封装复杂查询的MySQL视图,并创建一个独立的雄辩模型,该模型将从该视图中获取。这样,您的应用程序代码就可以像TickerLatest::all()一样简单。
发布于 2018-02-24 07:23:52
您可以先获取最新的行,然后对集合进行分组。
$items = Ticker::latest()->get();
// exchange, base, quote
$groupedByExchange = $items->groupBy('exchange');
$groupedByBase = $items->groupBy('base');
$groupedByQoute = $items->groupBy('qoute');UPDATE:您可以通过简单地在->first()函数之后添加groupBy()来获得每个组的单个项。
$latestByExchange= Ticker::latest()->groupBy('exchange')->first(); // and so on发布于 2018-02-24 08:09:06
可以将多个参数传递给groupBy方法,以按多列分组。
请参阅https://laravel.com/docs/5.6/queries#ordering-grouping-limit-and-offset文档
$users = DB::table('users')
->groupBy('first_name', 'status')
->having('account_id', '>', 100)
->get();https://stackoverflow.com/questions/48958737
复制相似问题