簡體   English   中英

MySQL查詢以在Chartjs中顯示數據

[英]MySql query to display data in Chartjs

我的用戶表帶有免費用戶或付費用戶的標志,並帶有注冊日期。 就像是

+------------+-----------+--------------+
| 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:['八月','九月','十月','十一月','十二月','一月']

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

但是我沒有達到我想要的。

您需要在每個月中生成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 ,並且計數不會增加。 或者,您可以在case表達式中使用else null

我將假設,一旦您將sql結果放入數組中,便可以將其應用於圖表的輸入中。

sqlfiddle上的演示

SQL

首先,您需要創建一個表(臨時表或其他表),該表代表最近6個月(tbl_agents中可能沒有任何記錄)。 您可以使用“聯合”語法和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

然后,我們可以在當月對tbl_agents使用LEFT JOIN並使用您現有的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);

暫無
暫無

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

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