簡體   English   中英

在Laravel中將數據綁定到DB :: raw()

[英]Bind data to DB::raw() in Laravel

我用原始SQL編寫了一個查詢,該查詢提取給定日期范圍內的所有記錄,根據插入日期和時間對記錄進行計數,並計算自插入“開始日期”以來的小時數。

我現在正在嘗試將該查詢填充到Laravel中。 我遇到的問題是,我需要一些Eloquent文檔中找不到的東西,因此我不得不使用DB::raw()來完成它們。 這對於硬編碼的值可以很好地工作,但是后來我意識到我需要使用動態值,這使我想到了這個問題 這個問題幾乎可以解決,但是我遇到的問題是,由於我使用帶變量的where子句,因此會引起一些奇怪的副作用。

例如,使用以下查詢:

$clicks = Tracker::select(DB::raw("TIME_TO_SEC(TIMEDIFF(DATE_FORMAT(actual_date,'%Y-%m-%d %H:00:00'),'?'))/60/60+1 as hours_since_send"), DB::raw('COUNT(*)'))
    ->where('actual_date', '>', $start_date)
    ->where('actual_date', '<', $end_date)
    ->whereIn('link_id', $link_ids)
    ->groupBy(DB::raw('DAY(actual_date)'))
    ->groupBy(DB::raw('HOUR(actual_date)'))
    ->orderBy('actual_date', 'asc')
    ->setBindings([$start_date])
    ->get();

給我這個錯誤:

SQLSTATE[HY093]: Invalid parameter number (SQL: select TIME_TO_SEC(TIMEDIFF(DATE_FORMAT(actual_date,'%Y-%m-%d %H:00:00'),'2014-10-02 00:00:00'))/60/60+1 as hours_since_send, COUNT(*) from `trackers` where `actual_date` > ? and `actual_date` < ? and `link_id` in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) group by DAY(actual_date), HOUR(actual_date) order by `actual_date` asc)

這似乎很簡單,所以我嘗試了:

$clicks = Tracker::select(DB::raw("TIME_TO_SEC(TIMEDIFF(DATE_FORMAT(actual_date,'%Y-%m-%d %H:00:00'),'?'))/60/60+1 as hours_since_send"), DB::raw('COUNT(*)'))
    ->where('actual_date', '>', $start_date)
    ->where('actual_date', '<', $end_date)
    ->whereIn('link_id', $link_ids)
    ->groupBy(DB::raw('DAY(actual_date)'))
    ->groupBy(DB::raw('HOUR(actual_date)'))
    ->orderBy('actual_date', 'asc')
    ->setBindings(array_merge([$start_date], $link_ids))
    ->get();

這給了我錯誤:

SQLSTATE[HY093]: Invalid parameter number (SQL: select TIME_TO_SEC(TIMEDIFF(DATE_FORMAT(actual_date,'%Y-%m-%d %H:00:00'),'2014-10-02 00:00:00'))/60/60+1 as hours_since_send, COUNT(*) from `trackers` where `actual_date` > 1156 and `actual_date` < 1157 and `link_id` in (1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, ?, ?) group by DAY(actual_date), HOUR(actual_date) order by `actual_date` asc)

因此,似乎setBindings只是覆蓋了laravel在后台設置的綁定。 我確實嘗試過用這些再次填充它們:

$clicks = Tracker::select(DB::raw("TIME_TO_SEC(TIMEDIFF(DATE_FORMAT(actual_date,'%Y-%m-%d %H:00:00'),'?'))/60/60+1 as hours_since_send"), DB::raw('COUNT(*)'))
    ->where('actual_date', '>', $start_date)
    ->where('actual_date', '<', $end_date)
    ->whereIn('link_id', $link_ids)
    ->groupBy(DB::raw('DAY(actual_date)'))
    ->groupBy(DB::raw('HOUR(actual_date)'))
    ->orderBy('actual_date', 'asc')
    ->setBindings(array_merge([$start_date, $start_date, $end_date], $link_ids))
    ->get();

盡管is不會引發錯誤,但它不會返回任何數據。

所以,我的問題是:如何在這樣的查詢中將DB::raw表達式與綁定參數一起使用,而又不會弄亂背景中的laravel集呢? 或者,我該如何重寫此查詢以完成我所需要的?

這是原始原始查詢供參考:

SELECT
  TIME_TO_SEC(TIMEDIFF(DATE_FORMAT(actual_date,'%Y-%m-%d %H:00:00'),'2014-10-02 00:00:00'))/60/60+1 as hours_since_send,
  COUNT(*)
FROM
  trackers
WHERE
  link_id BETWEEN 1156 AND 1171
  AND
  actual_date > '2014-10-02 00:00:00'
  AND actual_date < '2014-10-08 00:00:00'
GROUP BY
  DAY(actual_date),
  HOUR(actual_date)
ORDER BY
  actual_date

不要使用setBindings ,因為您不需要覆蓋所有的where綁定(這就是您所做的),只需執行以下操作:

$clicks = Tracker::select(DB::raw("TIME_TO_SEC(TIMEDIFF(DATE_FORMAT(actual_date,'%Y-%m-%d %H:00:00'),?))/60/60+1 as hours_since_send"), DB::raw('COUNT(*)'))
    ->addBinding($start_date, 'select')
    ->where('actual_date', '>', $start_date)
    ...

Eloquent實際上有一個whereBetween方法,該方法可以獲取兩個Carbon實例(以及正常的時間戳)並進行比較。

Tracker::whereBetween('actual_date', [$start, $end])->get(); 

http://laravel.com/docs/4.2/queries

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM