Laravel查询生成器 - 如何仅获取与查询匹配的最后一条记录

时间:2015-11-11 23:10:21

标签: mysql arrays laravel-5.1

使用Laravel 5.1我有一个股票表,其中包含一对多关系的股票代码和公司名称,价格表包含每15分钟更新一次的报价。任何人都可以告诉我最好的方法来获得从两个表的连接返回的最新报价?也许是我没有想过的另一种解决方案?这是我的联接,它为数据库中的每个股票和价格返回此信息。

$quotes = DB::table('stocks')
    ->join('stock_prices', 'stocks.id', '=', 'stock_prices.stock_id')
    ->get();
return $quotes;    

返回

[
{
"id": 25,
"symbol": "MSFT",
"last_price": "53.60",
},
{
"id": 25,
"symbol": "MSFT",
"last_price": "54.80",
},
{
"id": 30,
"symbol": "BA",
"last_price": "144.74",
},
{
"id": 30,
"symbol": "BA",
"last_price": "145.60",
},
] 

迁移

public function up()
{
    Schema::create('stock_prices', function (Blueprint $table) {
        $table->increments('id');
        $table->decimal('last_price', 6, 2);
        $table->decimal('net_change', 6, 2);
        $table->decimal('percent_change', 4, 2);
        $table->decimal('open', 6, 2);
        $table->decimal('high', 6, 2);
        $table->decimal('low', 6, 2);
        $table->decimal('close', 6, 2);
        $table->integer('volume');
        $table->integer('stock_id')->unsigned()->nullable();
        $table->timestamps();

        $table  ->foreign('stock_id')
                ->references('id')
                ->on('stocks')
                ->onDelete('cascade');
    });
}    

public function up()
{
    Schema::create('stocks', function (Blueprint $table) {
        $table->increments('id');
        $table->string('symbol');
        $table->string('name');
        $table->boolean('confirmed');
        $table->timestamps();
    });    

那么最好的方法是什么才能让它返回每个股票的最新更新价格?使用返回的数组或新的Laravel查询构建器?还是一个雄辩的解决方案?

我花了两天的时间搜索并将头撞在墙上,所以任何帮助都会非常感激。

附注:我计划清除30天以内的所有东西,因此桌子不会太大。另外,当用一些Laravel助手攻击数组时,我有时会得到一个错误,说它不是一个数组而是一个对象,有时会说它不是一个对象而是一个数组。奖金积分向我解释。

3 个答案:

答案 0 :(得分:0)

您可以使用 orderBy

$quotes = DB::table('stocks')
->join('stock_prices', 'stocks.id', '=', 'stock_prices.stock_id')
->orderBy('updated_at','desc')
->get();
return $quotes;  

答案 1 :(得分:0)

可以获得每股最新股票价格的原始查询类似于:

select s.id, s.symbol, sp.price, sp.updated from (
    select stock_id, max(updated) last_updated
    from   stock_price
    group by stock_id
) q
join stock_price sp on (q.stock_id = sp.stock_id and q.last_updated = sp.updated)
join stock s on (sp.stock_id = s.id)
;

获取每股股票stock_price的最新记录,然后加入stock_price获取价格并加入股票以获得符号。

使用查询构建器:

$groupBy = DB::table('stock_price')
->selectRaw('stock_id, max(updated) as last_updated')
->groupBy('stock_id');

$quotes = DB::table( DB::raw("({$groupBy->toSql()}) as q") )
->selectRaw('s.id, s.symbol, sp.price, sp.updated')
->mergeBindings($groupBy)
->join('stock_price as sp', function ($join) {
    $join->on('q.stock_id', '=', 'sp.stock_id')
         ->on('q.last_updated', '=', 'sp.updated');
})
->join('stock as s', 'q.stock_id', '=', 's.id')
->get();

牙齿有点长,最好使用原始sql。

答案 2 :(得分:0)

您可以在laravel中使用原始sql查询。它将返回结果作为对象的集合。此代码基于“当价格更新时,新记录将插入stock_prices表”。

$sql = "SELECT st.*, stp1.*
FROM stocks st
JOIN stock_prices stp1 ON (st.id = stp1.stock_id)
LEFT OUTER JOIN stock_prices stp2 ON (st.id = stp2.stock_id AND 
    (stp1.created_at < stp2.created_at OR stp1.created_at = stp2.created_at AND stp1.id < stp2.id))
WHERE stp2.id IS NULL";       

$result = DB::select(DB::raw($sql));
return $result;

我用小数据测试了它并返回了确切的结果。请查看您的数据。