从现在到 30 天前的几天分别获取 SQL 数据
Get SQL data individually for days between now and 30 days ago
我正在构建一个分析图表,我需要在其中显示过去 30 天内每天的访问次数。我试过使用下面的循环,但由于在一个请求中发送了 30 个查询,它无法提取某些数据并大大减慢了页面加载时间。
有没有更好的方法可以从 MySQL 数据库中获取这些数据,同时节省服务器资源并缩短页面加载时间?感谢任何帮助。
$conn = new mysqli("localhost", "db_host", "db_pwd", "db_name");
$d2 = date('c', strtotime('-29 days'));
$date = date("Y-m-d");
$begin = new DateTime($d2);
$end = new DateTime($date);
$end = $end->modify('+1 day');
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
foreach($daterange as $date){
$current = $date->format("Y-m-d");
$sql = "SELECT COUNT(*) FROM stats WHERE link_id=$_GET[id] AND date='$current'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) { echo $row["COUNT(*)"]; }
} else { echo "no results";}
}
$conn->close();
如果您每天至少访问一次,则可以只使用聚合:
select date(dt) as dt_day, count(*) as cnt_visits
from stats
where link_id = ? and dt >= current_date - interval 29 day
group by date(dt)
order by dt_day
有一个名为 date
的列在某种程度上具有误导性(尽管 MySQL 允许这样做)。为了清楚起见,我在查询中将该列重命名为 dt
。
如果有几天没有访问,你还想显示它们,统计0
次访问,那就有点棘手了。您需要先生成日期,然后 left join
table。您通常会使用日历 table - 或者,在 MySQL 8.0 中,您可以使用递归通用 table 表达式即时执行此操作:
with recursive cte as (
select current_date as dt_day
union all
select dt_day - interval 1 day from cte where dt_day > current_date - interval 29 day
)
select c.dt_day, count(s.dt) as cnt_visits
from cte c
left join stats s
on s.link_id = ?
and s.dt >= c.dt_day
and s.dt < c.dt_day + interval 1 day
group by c.dt_day
order by c.dt_day
我正在构建一个分析图表,我需要在其中显示过去 30 天内每天的访问次数。我试过使用下面的循环,但由于在一个请求中发送了 30 个查询,它无法提取某些数据并大大减慢了页面加载时间。
有没有更好的方法可以从 MySQL 数据库中获取这些数据,同时节省服务器资源并缩短页面加载时间?感谢任何帮助。
$conn = new mysqli("localhost", "db_host", "db_pwd", "db_name");
$d2 = date('c', strtotime('-29 days'));
$date = date("Y-m-d");
$begin = new DateTime($d2);
$end = new DateTime($date);
$end = $end->modify('+1 day');
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
foreach($daterange as $date){
$current = $date->format("Y-m-d");
$sql = "SELECT COUNT(*) FROM stats WHERE link_id=$_GET[id] AND date='$current'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) { echo $row["COUNT(*)"]; }
} else { echo "no results";}
}
$conn->close();
如果您每天至少访问一次,则可以只使用聚合:
select date(dt) as dt_day, count(*) as cnt_visits
from stats
where link_id = ? and dt >= current_date - interval 29 day
group by date(dt)
order by dt_day
有一个名为 date
的列在某种程度上具有误导性(尽管 MySQL 允许这样做)。为了清楚起见,我在查询中将该列重命名为 dt
。
如果有几天没有访问,你还想显示它们,统计0
次访问,那就有点棘手了。您需要先生成日期,然后 left join
table。您通常会使用日历 table - 或者,在 MySQL 8.0 中,您可以使用递归通用 table 表达式即时执行此操作:
with recursive cte as (
select current_date as dt_day
union all
select dt_day - interval 1 day from cte where dt_day > current_date - interval 29 day
)
select c.dt_day, count(s.dt) as cnt_visits
from cte c
left join stats s
on s.link_id = ?
and s.dt >= c.dt_day
and s.dt < c.dt_day + interval 1 day
group by c.dt_day
order by c.dt_day