[英]How to make sql query to group and sum results by date?
In yii2 app I have Payment
model with fields id
(primary key), u_id
(integer, means id of person that made this payment from User
model), sum
(integer) and date
. 在yii2应用程序中,我有
Payment
模型,字段id
(主键), u_id
(整数,表示从User
模型进行此付款的人的ID), sum
(整数)和date
。 Example: 例:
+--------------------------------+
| Payment |
+--------------------------------+
| id | u_id | sum | date |
+--------------------------------+
| 1 | 1 | 400 | 2015-11-25 |
| 2 | 1 | 200 | 2015-11-25 |
| 3 | 2 | 500 | 2015-11-25 |
| 4 | 2 | 300 | 2015-11-25 |
| 5 | 1 | 100 | 2015-11-20 |
+--------------------------------+
Q: I want to group results by date and summarize sum
fields of all rows for each u_id
for every day and also show total
row. 问:我想按日期对结果进行分组,并为每天的每个
u_id
汇总所有行的sum
字段,并显示total
。 How to do that...? 怎么做...? Maybe without
total
row? 也许没有
total
排? On yii2 or clean mysql . 在yii2 或干净的mysql 。 Example of results:
结果示例:
+-------------------------------------+
| Date | User id | Money, $ |
+-------------------------------------+
| 2015-11-25 | | 1400 (total) |
| 2015-11-25 | 1 | 600 |
| 2015-11-25 | 2 | 800 |
| 2015-11-20 | | 100 (total) |
| 2015-11-20 | 1 | 100 |
+-------------------------------------+
Payment
model: Payment
:
public function search($params)
{
$query = Payment::find();
// do we need to group and sum here?
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
return $dataProvider;
}
I guess ListView
will be easer then GridView
, because we will be able to make some calculations for each result. 我想
ListView
会比GridView
更容易,因为我们将能够为每个结果进行一些计算。 View: 视图:
<table>
<thead>
<tr>
<th>Date</th>
<th>User id</th>
<th>Money, $</th>
</tr>
</thead>
<tbody>
<?= ListView::widget([
'dataProvider' => $dataProvider,
'itemView' => '_item_view',
]) ?>
</tbody>
</table>
_item_view
: _item_view
:
<tr>
<td><?= $model->date ?></td>
<td><?= $model->u_id ?></td>
<td><?= $model->sum ?></td>
</tr>
Try this way: 试试这种方式:
select dt "Date", usr "User Id",
case when usr is null
then concat(money, ' (total)')
else money
end as "Money, $"
from (
select dt, null as usr, sum(vsum) as money
from mytable
group by dt
union
select dt, u_id, sum(vsum) as money
from mytable
group by dt, u_id
) a
order by dt desc, coalesce(usr,0)
See it here: http://sqlfiddle.com/#!9/48102/6 请在此处查看: http : //sqlfiddle.com/#!9/48102/6
What you need in plain MySql would be possible with analytical functions but since MySql doesn't support it, you have to emulate it. 你可以在普通的MySql中使用分析函数,但由于MySql不支持它,你必须模拟它。
In my solution, I've made a query that sum the money only by date 在我的解决方案中,我提出了一个只按日期汇总钱的查询
select dt, null as usr, sum(vsum) as money
from mytable
group by dt
The null as usr
column is needed so I can use the UNION
operator with the second part. 需要
null as usr
列,因此我可以将UNION
运算符与第二部分一起使用。 This query will get all dates and money summed. 此查询将汇总所有日期和金额。
Then the second part 然后是第二部分
select dt, u_id, sum(vsum) as money
from mytable
group by dt, u_id
Wich will get all dates by user summing the money. Wich将通过用户总结钱来获取所有日期。
The third part is to make it as subquery so I can order it with by date, user. 第三部分是使它成为子查询,所以我可以按日期,用户订购它。 Remember that the user of the first part is null, so I make it so every as null become
0
so it will be shown first. 请记住,第一部分的用户是null,所以我这样做,所以每当null变为
0
所以它将首先显示。
You can use a SqlDataProvider this way 您可以这种方式使用SqlDataProvider
$count = Yii::$app->db->createCommand('
SELECT COUNT(*) FROM payment group by `date`, u_id', )->queryScalar();
$dataProvider = new SqlDataProvider([
'sql' => 'SELECT u_id, sum(`sum`) as `sum` , `date` FROM payment group by `date`, u_id',
'totalCount' => $count,
'sort' => [
'attributes' => [
'u_id',
'sum',
'date',
],
],
'pagination' => [
'pageSize' => 20,
],
]);
return $this->render('index', [
'dataProvider' => $dataProvider,
]);
One option is let mysql calculate the totals using WITH ROLLUP
. 一个选项是让mysql使用
WITH ROLLUP
计算总数。
select dt, u_id, sum(vsum)
from payment
group by dt, u_id with rollup;
+------------+------+-----------+
| dt | u_id | sum(vsum) |
+------------+------+-----------+
| 2015-11-20 | 1 | 100 |
| 2015-11-20 | NULL | 100 |
| 2015-11-25 | 1 | 600 |
| 2015-11-25 | 2 | 800 |
| 2015-11-25 | NULL | 1400 |
| NULL | NULL | 1500 |
+------------+------+-----------+
If you don't want the overall total, you can eliminate that as well. 如果你不想要整体总数,你也可以消除它。
select * from (
select dt, u_id, sum(vsum)
from payment
group by dt, u_id with rollup
) q where dt is not null;
+------------+------+-----------+
| dt | u_id | sum(vsum) |
+------------+------+-----------+
| 2015-11-20 | 1 | 100 |
| 2015-11-20 | NULL | 100 |
| 2015-11-25 | 1 | 600 |
| 2015-11-25 | 2 | 800 |
| 2015-11-25 | NULL | 1400 |
+------------+------+-----------+
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.