我的用户表中包含免费用户或付费用户的标志以及注册日期。像
这样的东西+------------+-----------+--------------+
| USERNAME | FREE_USER | DATE_OF_REG |
+------------+-----------+--------------+
| user_name1 | y | 2018-01-14 |
| user_name2 | n | 2017-12-23 |
| user_name3 | y | 2017-12-12 |
| user_name4 | y | 2017-11-19 |
| user_name5 | n | 2017-09-13 |
| user_name6 | y | 2017-08-27 |
| user_name7 | n | 2017-07-06 |
+------------+-----------+--------------+
我需要过去6个月内free_users和paid_users的数量,如果一个月内没有用户注册,则应该将0作为免费和付费计数。
我想为免费用户和付费用户创建折线图,就像在此示例中一样(http://www.chartjs.org/samples/latest/charts/line/basic.html)。为此我需要以逗号(,)分隔格式的数据,如:
month_of_registration:[' August',' September',' October',' November',' December' ,' 1月']
free_users_count_for_related_month:[0,1,0,1,0,1,1]
paid_users_count_for_related_month:[1,0,1,0,0,1,0]
如何在PHP中使用mysql查询实现此目的。
我写了这个查询:
SELECT MONTH(date_of_reg) as monthno, MONTHNAME(date_of_reg) as month_name, YEAR(date_of_reg) as year,
COUNT(CASE WHEN `free_user` = 'y' THEN 1 END) AS free_user,
COUNT(CASE WHEN `free_user` = 'n' THEN 1 END) AS paid,
COUNT(CASE WHEN `free_user` != '' THEN 1 END) as total_users
FROM tbl_agents GROUP BY MONTH( date_of_reg ) ORDER BY year, monthno
但我没有达到我想要的目标。
答案 0 :(得分:3)
您需要为这几个月生成6行,因为注册中可能存在空白,并且您需要决定何时开始,我使用下面的当前日期作为该点,但它可以是任何想要的日期。注意我从那个日期开始倒退。
此子查询将日期与当月的开头和下个月的第一天进行比较:
set @datum := DATE_FORMAT(current_date, '%Y-%m-01');
...
cross join (select @datum dt_fm, @datum + interval 1 month dt_to) d
然后,当加入6行数字(0到5)时,我们计算过去6个月的日期范围,然后它们允许我们将注册放入每月的桶中进行计数。
set @datum := DATE_FORMAT(current_date, '%Y-%m-01');
select
monthname(dt_fm - interval n.n month) mnth
, dt_fm - interval n.n month dt_fm
, dt_to - interval n.n month dt_to
, count(case when t.free_user = 'y' then 1 end) free_users
, count(case when t.free_user = 'n' then 1 end) paid_users
from (
select 0 n union all
select 1 n union all
select 2 n union all
select 3 n union all
select 4 n union all
select 5 n
) n
cross join (select @datum dt_fm, @datum + interval 1 month dt_to) d
left join tbl_agents t on t.DATE_OF_REG >= dt_fm - interval n.n month
and t.DATE_OF_REG < dt_to - interval n.n month
group by
monthname(dt_fm - interval n.n month)
, dt_fm - interval n.n month
, dt_to - interval n.n month
order by dt_fm
;
结果:
| mnth | dt_fm | dt_to | free_users | paid_users |
|-----------|------------|------------|------------|------------|
| August | 2017-08-01 | 2017-09-01 | 1 | 0 |
| September | 2017-09-01 | 2017-10-01 | 0 | 1 |
| October | 2017-10-01 | 2017-11-01 | 0 | 0 |
| November | 2017-11-01 | 2017-12-01 | 1 | 0 |
| December | 2017-12-01 | 2018-01-01 | 1 | 1 |
| January | 2018-01-01 | 2018-02-01 | 1 | 0 |
请注意,count()
函数会忽略null
,因此case表达式不使用else
,因此当表达式不符合null
时,会计算else null
没有增加。或者,您可以在案例表达式中使用declare
v_timestamp timestamp(6);
begin
select max("MODIFIED_ON") into v_timestamp from "public"."DAS_ITEM"@PG_LINK;
dbms_output.put_line(v_timestamp);
end;
。
我将假设一旦你在数组中得到sql结果,你就可以将其用于图表的输入。
答案 1 :(得分:1)
<强> SQL 强>
首先,你需要创建一个代表过去6个月的表(临时或其他)(tbl_agents可能没有任何记录)。你可以使用&#34; union&#34;语法和date_sub函数(这样可以很容易地跟踪发生的事情):
select now() as month union
select date_sub(now(), INTERVAL 1 MONTH) as month union
select date_sub(now(), INTERVAL 2 MONTH) as month union
select date_sub(now(), INTERVAL 3 MONTH) as month union
select date_sub(now(), INTERVAL 4 MONTH) as month union
select date_sub(now(), INTERVAL 5 MONTH) as month union
select date_sub(now(), INTERVAL 6 MONTH) as month
输出:
month
2018-01-25T03:04:22Z
2017-12-25T03:04:22Z
2017-11-25T03:04:22Z
2017-10-25T03:04:22Z
2017-09-25T03:04:22Z
2017-08-25T03:04:22Z
2017-07-25T03:04:22Z
然后我们可以在月份使用LEFT JOIN到tbl_agents并使用现有的SQL来实现必要的输出。请注意,我们正在上面的临时表中提供日期:
SELECT MONTH(m.month) AS monthno,
MONTHNAME(m.month) as month_name,
YEAR(m.month) as year,
SUM(CASE WHEN `free_user` = 'y' THEN 1 ELSE 0 END) AS free_user,
SUM(CASE WHEN `free_user` = 'n' THEN 1 ELSE 0 END) AS paid,
SUM(CASE WHEN `free_user` != '' THEN 1 ELSE 0 END) as total_users
FROM (
select now() as month union
select date_sub(now(), INTERVAL 1 MONTH) as month union
select date_sub(now(), INTERVAL 2 MONTH) as month union
select date_sub(now(), INTERVAL 3 MONTH) as month union
select date_sub(now(), INTERVAL 4 MONTH) as month union
select date_sub(now(), INTERVAL 5 MONTH) as month union
select date_sub(now(), INTERVAL 6 MONTH) as month
) AS m
LEFT JOIN tbl_agents as tb
ON MONTH(tb.DATE_OF_REG) = MONTH(m.month)
GROUP BY MONTH(tb.DATE_OF_REG)
ORDER BY m.month DESC;
输出:
| monthno | month_name | year | free_user | paid | total_users |
|---------|------------|------|-----------|------|-------------|
| 1 | January | 2018 | 1 | 0 | 1 |
| 12 | December | 2017 | 1 | 1 | 2 |
| 11 | November | 2017 | 1 | 0 | 1 |
| 10 | October | 2017 | 0 | 0 | 0 |
| 9 | September | 2017 | 0 | 1 | 1 |
| 8 | August | 2017 | 1 | 0 | 1 |
| 7 | July | 2017 | 0 | 1 | 1 |
你可以在这个小提琴中看到这个:http://sqlfiddle.com/#!9/5ad682/12/0
<强> PHP 强>
您的示例中所需的输出是JSON - 因此您需要做的就是从MySQL获取数据并构建表示输出的数组,然后再转换为JSON。例如,它可能看起来像:
<?php
//$data = mysql_query_results
$output_array = array('month_of_registration' => array(),
'free_users_count_for_related_month' => array(),
'paid_users_count_for_related_month' => array());
foreach( $data as $e ) {
$output_array['month_of_registration'][] = $e['month_name'];
$output_array['free_users_count_for_related_month'][] = $e['free_user'];
$output_array['paid_users_count_for_related_month'][] = $e['paid'];
}
$output_data = json_encode($output_array);