【问题标题】:Convert MySQL Query into JSON using PHP使用 PHP 将 MySQL 查询转换为 JSON
【发布时间】:2015-10-31 17:36:15
【问题描述】:

我有一个关于使用 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);

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

EDIT2 - 我正在考虑另一种处理方法是将多个 SELECT 语句组合成一个 JSON 对象,但我不确定如何执行此操作。

【问题讨论】:

  • 您的查询是否成功返回数据?有什么问题?输出是什么,解释清楚。您使用的标头是什么?
  • 是的,查询成功返回数据。问题是它只返回所有四个表都有信息的日期的数据,而不是显示所有日期的数据,即使一个表必须有数据。它还输出 nf_sugars 和 nf_total_carbohydrate 的总和,该总和高于我数据库中数字的实际总和。我不确定这是否与我根据日期加入表格这一事实有关,即使有些表格每天有多次提交而其他表格没有。
  • 在原始 SQL 上检查您的查询,看看它是否正确,在命令行或 PHPMyAdmin 或类似的东西上检查它。您说它只返回“日期数据”,这意味着它没有正确返回。

标签: php mysql json


【解决方案1】:

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

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

其次,确保您捕获所有数据,即使在某个日期并非所有表格都有 值,您应该使用完整的外部连接。这将保证每个表中的每条记录 将在结果中找到它的方式。现在,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 中编写代码。

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

【讨论】:

  • 非常感谢您的评论!通过 PHPMyAdmin 运行此程序时,我收到以下错误:#1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以了解在 'FULL OUTER JOIN 附近使用的正确语法
  • 确实,我现在意识到 MySql 不支持 FULL OUTER JOIN。我已经调整了我的答案以避免使用它。
  • 非常感谢您的帮助。运行时出现以下错误:#1248 - 每个派生表都必须有自己的别名
  • 现在我得到:#1054 - '字段列表'中的未知列 'sum_nf_sugars'
  • 已更正。里面有一个 sum_nf_sugars_sum,最后不应该有 _sum 部分。
【解决方案2】:

我更喜欢使用这种方式(假设所有其他东西都工作正常,例如 query 工作正常)

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

if ( ! $query ) {
    echo mysqli_error($conn);  //You need to put $conn here to display error.
    die;
}

$data = array();

while($row = mysqli_fetch_assoc($query)) {
    $data[] = $row;
}

echo json_encode($data);     

mysqli_close($conn);

【讨论】:

    【解决方案3】:

    如果您使用 PDO(PHP 数据对象)进行数据库操作;然后可以使用以下代码从 PDO 创建 JSON。

    $array = $pdo->query("SELECT * FROM employee")->fetchAll(PDO::FETCH_ASSOC);
    echo json_encode($array);
    

    对于多选,我们需要这样尝试:

    $array = $pdo->query("SELECT 1; SELECT 2;");
    $array->nextRowset();
    var_dump( $array->fetchAll(PDO::FETCH_ASSOC) );
    

    【讨论】:

    • 感谢您的评论。我需要从多个表中进行选择。是否可以使用此方法运行多个选择并返回单个 JSON 对象?
    • 你能用多个 select 语句展示这个例子吗?我不确定如何连接它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    • 2021-07-04
    • 2020-09-19
    • 1970-01-01
    相关资源
    最近更新 更多