Suma jest większa niż oczekiwano z powodu sprzężeń. Wyobraź sobie, że pewna data występuje w jednym rekordzie track_nutrition i dwóch rekordach track_fatigue, a następnie sprzężenie spowoduje, że dane z pierwszej tabeli zostaną raz połączone z pierwszym rekordem track_fatiguerecord, a następnie ponownie z drugim rekordem. W ten sposób ta sama wartość nf_sugars zostanie liczona dwukrotnie w sumie. To zachowanie wpłynie również na średnie.
Dlatego powinieneś najpierw wykonać agregacje, a dopiero potem wykonać łączenia.
Po drugie, aby mieć pewność, że przechwycisz wszystkie dane, nawet jeśli dla określonej daty nie wszystkie tabele mają wartości, powinieneś użyć pełnych sprzężeń zewnętrznych. Zagwarantuje to, że każdy rekord w każdej tabeli znajdzie się w wyniku. Teraz MySQL nie obsługuje takich pełnych złączeń zewnętrznych, więc używam dodatkowego podselekcji, aby wybrać wszystkie różne daty z 4 tabel, a następnie „złączyć je w lewo” z innymi zagregowanymi danymi:
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;
Zwróć uwagę, że w niektórych kolumnach otrzymasz 0 wartości, jeśli nie ma danych dla tej konkretnej daty. Jeśli wolisz uzyskać NULL
zamiast tego usuń Nvl() z tych kolumn w powyższym zapytaniu.
Następnie, aby znormalizować wszystkie dane w skali od 0 do 10, możesz spojrzeć na maksimum znalezione dla każdego typu wartości i użyć tego do konwersji lub jeśli wiesz wcześniej, jakie są zakresy dla poszczególnych typów, prawdopodobnie lepiej jest użyć tego informacje, a może również kod w SQL.
Jednak zawsze wygląda to trochę dziwnie, gdy wartości są połączone na wykresie, który faktycznie używa różnych skal. Na takich wykresach można łatwo dojść do błędnych wniosków.