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