php - 使用 PHP 将 MySQL 查询转换为 JSON

标签 php mysql json

我有一个关于使用 MySQL 查询将我的数据转换为 JSON 对象的问题。我的查询正在转换为 JSON 对象,但它没有按照我希望的方式工作。

我的数据库中有多个表,我想使用日期作为 X 轴并使用值作为 Y 轴在图表上绘制图表。我目前正在按日期加入表格。但是,某些表可能每天有多次提交,而其他表可能没有。目前,我的查询只显示数据提交到所有 4 个表的日期的结果。

我还想以 0-10 的比例绘制信息图表。 4 个表中的三个只有 0-10 之间的值,所以我每天取每个值的平均值。包含 nf_sugars 和 nf_total_carbohydrates 的营养表具有更大的数字,我将使用归一化将它们转换为 0-10 的比例。现在,我只是尝试获取每天的 SUM,并将在这部分工作后完成剩余的计算。但是,我当前运行的查询给我的结果比数据库中实际数字的总和高得多。

任何帮助将不胜感激!这是我目前用来创建 JSON 对象的 PHP。作为旁注,我确实成功连接到我的数据库,我只是没有在此处包含它。

 $myquery = "SELECT  track_ticseverity.date,
                AVG(track_ticseverity.ticnum) as average_ticnum, 
                 track_fatigue.date, 
                AVG(track_fatigue.fatiguenum) as average_fatiguenum, 
                track_stress.date,
                AVG(track_stress.stressnum) as average_stressnum, 
                track_nutrition.date,
                ((SUM(track_nutrition.nf_sugars) ) ) as sum_nf_sugars, 
                ((SUM(track_nutrition.nf_total_carbohydrate) ) ) as sum_nf_total_carbohydrate 
          FROM track_ticseverity
          INNER JOIN track_fatigue
            ON track_ticseverity.date=track_fatigue.date
          INNER JOIN track_stress
            ON track_fatigue.date=track_stress.date
          INNER JOIN track_nutrition
            ON track_stress.date=track_nutrition.date
          WHERE track_ticseverity.user_id=1
          AND track_fatigue.user_id=1
          AND track_stress.user_id=1
          AND track_nutrition.user_id=1
          GROUP BY track_ticseverity.date";


$query = mysqli_query($conn, $myquery);

if ( ! $query ) {
    echo mysqli_error(s);
    die;
}

$data = array();

for ($x = 0; $x < mysqli_num_rows($query); $x++) {
    $data[] = mysqli_fetch_assoc($query);
}

echo json_encode($data);     

mysqli_close($conn);

编辑 - 查询成功返回一个 JSON 对象。我的问题是我编写的查询没有以正确的方式输出数据。我需要查询从多个表中选择信息,一些表每天提交多次,而另一些表只提交一次或不提交。

EDIT2 - 我正在考虑另一种处理方法是将多个 SELECT 语句合并到一个 JSON 对象中,但我不确定该怎么做。

最佳答案

由于连接,总和大于预期。想象一下某个日期 出现在一个 track_nutrition 记录和两个 track_fatigue 记录中,然后加入 将使第一个表中的数据与第一个 track_fatigue 结合 记录,然后再次记录第二条记录。因此相同的 nf_sugars value 将在总和中计算两次。此行为也会影响平均值。

因此,您应该首先执行聚合,然后才执行连接。

其次,确保您捕获所有数据,即使在某个特定日期并非所有表都有 值,您应该使用完全外部联接。这将保证每个表中的每条记录 会在结果中找到它的方式。现在,MySQL 不支持这种全外连接,所以 我使用额外的子选择从 4 个表中选择所有不同的日期,然后 将它们与其他聚合数据“左连接”:

SELECT      dates.date,
            IFNULL(average_ticnum_n, 0)            as average_ticnum 
            IFNULL(average_fatiguenum_n, 0)        as average_fatiguenum  
            IFNULL(average_stressnum_n, 0)         as average_stressnum
            IFNULL(sum_nf_sugars_n, 0)             as sum_nf_sugars 
            IFNULL(sum_nf_total_carbohydrate_n, 0) as sum_nf_total_carbohydrate  
FROM        (
                    SELECT DISTINCT user_id,
                                    date
                    FROM (
                            SELECT   user_id,
                                     date
                            FROM     track_ticseverity
                            UNION     
                            SELECT   user_id,
                                     date
                            FROM     track_fatigue
                            UNION     
                            SELECT   user_id,
                                     date
                            FROM     track_stress
                            UNION     
                            SELECT   user_id,
                                     date
                            FROM     track_nutrition
                    ) as combined 
            ) as dates
LEFT JOIN   (
                    SELECT   user_id,
                             date,
                             AVG(ticnum) as average_ticnum_n
                    FROM     track_ticseverity
                    GROUP BY user_id,
                             date) as grp_ticseverity
        ON  dates.date = grp_ticseverity.date
        AND dates.user_id = grp_ticseverity.user_id
LEFT JOIN   (
                    SELECT   user_id,
                             date, 
                             AVG(fatiguenum) as average_fatiguenum_n
                    FROM     track_fatigue
                    GROUP BY user_id,
                             date) as grp_fatigue
        ON  dates.date = grp_fatigue.date
        AND dates.user_id = grp_fatigue.user_id
LEFT JOIN   (
                    SELECT   user_id,
                             date,
                             AVG(stressnum) as average_stressnum_n
                    FROM     track_stress
                    GROUP BY user_id,
                             date) as grp_stress
        ON  dates.date = grp_stress.date
        AND dates.user_id = grp_stress.user_id
LEFT JOIN   (
                    SELECT   user_id,
                             date,
                             SUM(nf_sugars) as sum_nf_sugars_n,
                             SUM(nf_total_carbohydrate) as sum_nf_total_carbohydrate_n
                    FROM     track_nutrition
                    GROUP BY user_id,
                             date) as grp_nutrition
        ON  dates.date = grp_nutrition.date
        AND dates.user_id = grp_nutrition.user_id
WHERE       dates.user_id = 1
ORDER BY    dates.date;

请注意,当某些列没有数据时,您将在某些列中获得 0 值 特定日期。如果您希望获得 NULL,请从这些列中删除 Nvl() 在上面的查询中。

然后,要在 0 - 10 范围内标准化所有数据,您可以查看最大值 找到每种类型的值并将其用于转换,或者如果您事先知道 每种类型的范围是多少,那么最好使用该信息,并且 也许也可以在 SQL 中编写代码。

但是,将值组合在实际使用的图表中总是看起来有点奇怪 不同的尺度。人们可能很容易通过此类图表得出错误的结论。

关于php - 使用 PHP 将 MySQL 查询转换为 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33454545/

相关文章:

mysql - 当记录通常已经存在时如何有效地使用 first_or_initialize

javascript - 使用来自 Processing-JS 的 JSON

ios - UILocalNotification 没有出现

php - 关闭浏览器后清除缓存 - symfony2

php - 使用查询生成器在 Laravel 中添加全文索引

php - 阻止 Codeigniter Cron 作业的 session

mysql - 使用单个查询将值插入多个表

php - 如何在不更改 php.ini max_execution_time 的情况下避免超过 60 秒的最大执行时间 Laravel

php - 使用 mysql 返回 2 个日期之间的特定元素

java - 对象与 JSON 之间的转换