在yii2应用中,我的Payment
模型包含字段id
(主键),u_id
(整数,表示从User
模型付款的人的ID) ,sum
(整数)和date
。例如:
+--------------------------------+
| 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 |
+--------------------------------+
问:我希望按日期对结果进行分组,并每天为每个sum
汇总所有行的u_id
个字段,并显示total
行。怎么做...?也许没有total
行?在yii2 或清除mysql 。结果示例:
+-------------------------------------+
| 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
型号:
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;
}
我猜ListView
会更加轻松GridView
,因为我们可以为每个结果进行一些计算。视图:
<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
:
<tr>
<td><?= $model->date ?></td>
<td><?= $model->u_id ?></td>
<td><?= $model->sum ?></td>
</tr>
答案 0 :(得分:3)
尝试这种方式:
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)
在此处查看: http://sqlfiddle.com/#!9/48102/6
您可以使用分析函数在普通MySql中获得所需的内容,但由于MySql不支持它,因此您必须模拟它。
在我的解决方案中,我已经提出了一个只按日期汇总资金的查询
select dt, null as usr, sum(vsum) as money
from mytable
group by dt
需要null as usr
列,因此我可以将UNION
运算符与第二部分一起使用。此查询将汇总所有日期和金额。
然后是第二部分
select dt, u_id, sum(vsum) as money
from mytable
group by dt, u_id
将由用户汇总所有日期。
第三部分是将它作为子查询,以便我可以按日期,用户订购。请记住,第一部分的用户为null,因此我将其设置为null,因为它将变为0
,因此它将首先显示。
答案 1 :(得分:1)
您可以这样使用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,
]);
答案 2 :(得分:1)
一个选项是让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 |
+------------+------+-----------+
如果你不想要总数,你也可以消除它。
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 |
+------------+------+-----------+