我也看到过类似的问题,但老实说,我没有发现任何可以使我正确的方法,这是因为我也在寻找一种更好的方法。
在我的应用程序中的某些时候,我正在使用chartjs,我需要在其中显示月份,然后显示值(销售额)。为此,我知道(或我认为)我必须按月检索分组的数据,而到目前为止,我到了这里:
$records = TabelaAngariacao::select('preco', 'created_at')
->where('estado', '=', 'Vendido')
->get()
->groupBy(function($date) {
return Carbon::parse($date->created_at)->format('m');
});
好吧...正如您所看到的,我什么都没有求和,那是因为在我的数据库中,我的值被存储在varchar中(带点号!),我知道这不是正确的处理方式,但是此时更改所有内容对我来说现在不是解决方案,所以我该如何更改该功能以删除点并执行适当的金额?我已经尝试过使用CAST,但是它给了我未定义的功能。
有什么建议吗?谢谢您的时间,问候。
-编辑-
大家好,我想我已经快到了,我不知道 transform函数,在那里我可以对preco(price)字段进行一些修改,但这仍然有问题因为是varchar,所以我需要删除点以使总和起作用,我所拥有的是:
$records = TabelaAngariacao::select('preco', 'created_at')
->where('estado', '=', 'Vendido')
->get()
->groupBy(function($date) {
return Carbon::parse($date->created_at)->format('m');
})->transform(function ($value) { //it can also be map()
$nStr = str_replace(".", "", $value->pluck('preco'));
return [
'preco_sum' => $nStr->sum()
];
});
但是这不起作用,因为$ nStr是字符串...我需要做什么?如果我转换为浮点数,那么总和将不起作用...如果我这样离开,则175.000和1.000.000之间的总和将为176.000,这是错误的...有什么想法吗?
答案 0 :(得分:0)
尝试此查询。
$records = TabelaAngariacao::select(
\DB::raw('sum(cast(preco as double precision)) as sums'),
\DB::raw("DATE_FORMAT(created_at,'%M %Y') as months"))
->where('estado', '=', 'Vendido')
->groupby('months')->get();
答案 1 :(得分:0)
我这样做是为了进行汇总和按月分组
$ventas = Operacion::select([
DB::raw("DATE_FORMAT(created_at, '%Y') year"),
DB::raw("DATE_FORMAT(created_at, '%m') month"),
DB::raw("SUM(1) cantidad"),
DB::raw("SUM(operacion_total) total"),
DB::raw("SUM(CASE WHEN estado = 'OPEFIN' THEN operacion_total ELSE 0 END) total_finalizado")
])->groupBy('year')->groupBy('month')->get();
如果您需要转换一些varchar,可以这样做
CAST(operacion_total as DECIMAL(9,2))
所以选择中的一列可能是
DB::raw("SUM(CAST(operacion_total as DECIMAL(9,2))) total"),
请尝试一下,让我知道它如何工作:)
答案 2 :(得分:0)
Friend, if you want to make use of collection to group and also sum the values in group I believe its not too late.
Let's use the example below:
I'll make a sample result of your eloquent query with the following... Say we have users
$users = collect();
foreach (range(1, 9) as $item) {
foreach (range(1, 9) as $ninja) {
$users->push([
'created_at' => \carbon('2018-0' . $item),
'preco' => (string)'160.00' . $item
]);
}
}
The above should have something like this...
[
{
"created_at": "2018-01-01 00:00:00",
"preco": "160.001"
},
{
"created_at": "2018-01-01 00:00:00",
"preco": "160.001"
},
{
"created_at": "2018-01-01 00:00:00",
"preco": "160.001"
},
...
]
We then group by, and transform (or map) the result using...
$users->map(function ($user) {
$user['preco'] = str_replace('.', '', $user['preco']);
return $user;
})->groupBy(function ($user) {
return Carbon::parse($user['created_at'])->format('m');
})->transform(function ($value, $key) { //it can also be map()
return [
'preco_sum' => $value->pluck('preco')->sum()
];
});
Here we have the sum of each of the group of months...
UPDATE
If the record is big, then you can cut down the map
ping by using Accessor
You could have something as follows that formats your 'preco' field in your model like so:
/**
* Get the user's first name.
*
* @param string $value
* @return string
*/
public function getPrecoAttribute($value)
{
return str_replace('.', '', $value);
}
This means when Laravel is building the Eloquent objects, this value would be formatted as specified which means you can remove the first map()
from the result.
PS: you might need a mutator to change it to the format you want it in the database when saving.
Cheers!