我有以下查询,它会显示特定区域的每分钟温度和相对湿度信息:
SELECT plands.land AS Land,
ROUND(AVG(meteorology.temperature),2) AS Temperatureday,
ROUND(AVG(meteorology.humidity),2) AS Humidityday,
WEEKOFYEAR(meteorology.date) AS Week
FROM meteorology
INNER JOIN plands ON plands.id = meteorology.id_land
WHERE DATE(meteorology.date) BETWEEN '2016-09-12' AND '2016-09-23'
AND TIME(meteorology.date) >= '06:00:00'
AND TIME(meteorology.date) <= '18:00:00'
GROUP BY meteorology.id_land,
WEEKOFYEAR(meteorology.date),
YEAR(meteorology.date)
UNION ALL
SELECT plands.land AS Land,
ROUND(AVG(meteorology.temperature),2) AS TemperatureNight,
ROUND(AVG(meteorology.humidity),2) AS HumidityNight,
WEEKOFYEAR(meteorology.date) AS Week
FROM meteorology
INNER JOIN plands ON plands.id = meteorology.id_land
WHERE DATE(meteorology.date) BETWEEN '2016-09-12' AND '2016-09-23'
AND (TIME(meteorology.date) < '06:00:00'
OR TIME(meteorology.date) > '18:00:00')
GROUP BY meteorology.id_land,
WEEKOFYEAR(meteorology.date),
YEAR(meteorology.date)
它显示以下内容:
----------------------------------------------------------
Land | Temperatureday | Humidityday | Week |
----------------------------------------------------------
LAND1 | 16.13 | 92.03 | 37 |
----------------------------------------------------------
LAND1 | 16.46 | 84.35 | 38 |
----------------------------------------------------------
LAND1 | 9.37 | 99.0 | 37 |
----------------------------------------------------------
LAND1 | 9.95 | 99.0 | 38 |
----------------------------------------------------------
但我要将数据显示如下:
------------------------------------------------------------------------------
Land | Temperatureday | Humidityday |TemperatureNight | HumidityNigh |Week|
------------------------------------------------------------------------------
LAND1 | 16.13 | 92.03 | 9.37 | 99.0 | 37 |
------------------------------------------------------------------------------
LAND1 | 16.46 | 84.35 | 9.95 | 99.0 | 38 |
------------------------------------------------------------------------------
我知道我的查询错了,但我不知道我做了什么。
谢谢!
答案 0 :(得分:2)
加入你的2个查询而不是联合它们:
SELECT day.Week, day.land,
day.Temperature, day.Humidity,
night.Temperature, night.Humidity,
FROM
(
SELECT plands.land AS Land,
ROUND(AVG(meteorology.temperature),2) AS Temperature,
ROUND(AVG(meteorology.humidity),2) AS Humidity,
WEEKOFYEAR(meteorology.date) AS Week
FROM meteorology
INNER JOIN plands ON plands.id = meteorology.id_land
WHERE DATE(meteorology.date) BETWEEN '2016-09-12' AND '2016-09-23'
AND TIME(meteorology.date) >= '06:00:00'
AND TIME(meteorology.date) <= '18:00:00'
GROUP BY meteorology.id_land,
WEEKOFYEAR(meteorology.date),
YEAR(meteorology.date)
) day LEFT JOIN (
SELECT plands.land AS Land,
ROUND(AVG(meteorology.temperature),2) AS Temperature,
ROUND(AVG(meteorology.humidity),2) AS Humidity,
WEEKOFYEAR(meteorology.date) AS Week
FROM meteorology
INNER JOIN plands ON plands.id = meteorology.id_land
WHERE DATE(meteorology.date) BETWEEN '2016-09-12' AND '2016-09-23'
AND (TIME(meteorology.date) < '06:00:00'
OR TIME(meteorology.date) > '18:00:00')
AND meteorology.id_tenant = 1
GROUP BY meteorology.id_land,
WEEKOFYEAR(meteorology.date),
YEAR(meteorology.date)
) night
ON day.land=night.land
AND day.Week=Night.Week
请注意,这不是非常有效,更好的解决方案是实现单个数据传递 - 但是这个代码相当混乱.... ......的内容...... >
SELECT plands.land as Land,
ROUND(SUM(CASE WHEN TIME(meteorology.date) >= '06:00:00'
AND TIME(meteorology.date) <= '18:00:00'
THEN meteorology.temperature
ELSE 0 END)
/
SUM(CASE WHEN TIME(meteorology.date) >= '06:00:00'
AND TIME(meteorology.date) <= '18:00:00'
THEN 1
ELSE 0 END), 2) AS DayTemperature,
...
答案 1 :(得分:2)
另一种加入数据的方法涉及日期数据的子查询,您将夜间数据JOIN
作为第二个外部查询的附加详细信息。这在将子查询实现为临时表(例如MySQL)的查询引擎中很有效。
SELECT wxday.Land, Temperatureday, Humidityday,
ROUND(AVG(meteorology.temperature),2) AS TemperatureNight,
ROUND(AVG(meteorology.humidity),2) AS HumidityNight,
wxday.Week
FROM (
SELECT plands.land AS Land,
ROUND(AVG(meteorology.temperature),2) AS Temperatureday,
ROUND(AVG(meteorology.humidity),2) AS Humidityday,
WEEKOFYEAR(meteorology.date) AS Week,
YEAR(meteorology.date) AS Year
FROM meteorology
INNER JOIN plands ON plands.id = meteorology.id_land
WHERE DATE(meteorology.date) BETWEEN '2016-09-12' AND '2016-09-23'
AND TIME(meteorology.date) >= '06:00:00'
AND TIME(meteorology.date) <= '18:00:00'
GROUP BY meteorology.id_land,
WEEKOFYEAR(meteorology.date),
YEAR(meteorology.date)
) AS wxday
INNER JOIN meteorology
ON (wxday.Land = meteorology.id_land
AND WEEKOFYEAR(meteorology.date) = wxday.Week
AND YEAR(meteorology.date) = wxday.Year)
WHERE DATE(meteorology.date) BETWEEN '2016-09-12' AND '2016-09-23'
AND (TIME(meteorology.date) < '06:00:00'
OR TIME(meteorology.date) > '18:00:00')
GROUP BY wxday.Land, wxday.Week, wxday.Year
第二种方法保留UNION
,将日夜数据放在单独的输出列中,然后使用MIN
将它们组合起来。这是有效的,因为具有一个非空值和一个MIN
的组的NULL
是一个非空值。如果几周有夜间数据但没有日期数据,反之亦然,它可能会更好:
SELECT Land,
MIN(Temperatureday) AS Temperatureday,
MIN(Humidityday) AS Humidityday,
MIN(TemperatureNight) AS TemperatureNight,
MIN(HumidityNight) AS HumidityNight,
Week
FROM (
SELECT plands.land AS Land,
ROUND(AVG(meteorology.temperature),2) AS Temperatureday,
ROUND(AVG(meteorology.humidity),2) AS Humidityday,
NULL AS TemperatureNight,
NULL AS HumidityNight,
WEEKOFYEAR(meteorology.date) AS Week,
YEAR(meteorology.date) AS Year
FROM meteorology
INNER JOIN plands ON plands.id = meteorology.id_land
WHERE DATE(meteorology.date) BETWEEN '2016-09-12' AND '2016-09-23'
AND TIME(meteorology.date) >= '06:00:00'
AND TIME(meteorology.date) <= '18:00:00'
GROUP BY meteorology.id_land,
WEEKOFYEAR(meteorology.date),
YEAR(meteorology.date)
UNION ALL
SELECT plands.land AS Land,
NULL AS TemperatureNight,
NULL AS HumidityNight,
ROUND(AVG(meteorology.temperature),2) AS TemperatureNight,
ROUND(AVG(meteorology.humidity),2) AS HumidityNight,
WEEKOFYEAR(meteorology.date) AS Week,
YEAR(meteorology.date) AS Year
FROM meteorology
INNER JOIN plands ON plands.id = meteorology.id_land
WHERE DATE(meteorology.date) BETWEEN '2016-09-12' AND '2016-09-23'
AND (TIME(meteorology.date) < '06:00:00'
OR TIME(meteorology.date) > '18:00:00')
GROUP BY meteorology.id_land,
WEEKOFYEAR(meteorology.date),
YEAR(meteorology.date)
) AS itsownalias
GROUP BY Land, Week, Year
第三种方法是通过数据传递并使用AVG
,依赖于其相同的NULL
- 跳过行为。这也可以在没有子查询的情况下表达,但IsDay
使其更具可读性,更符合"Don't repeat yourself" principle。
SELECT Land,
ROUND(AVG(CASE IsDay WHEN 0 THEN NULL ELSE temperature END),2) AS Temperatureday,
ROUND(AVG(CASE IsDay WHEN 0 THEN NULL ELSE humidity END),2) AS Humidityday,
ROUND(AVG(CASE IsDay WHEN 0 THEN temperature ELSE NULL END),2) AS TemperatureNight,
ROUND(AVG(CASE IsDay WHEN 0 THEN humidity ELSE NULL END),2) AS HumidityNight,
WEEKOFYEAR(meteorology.date) AS Week
FROM (
SELECT plands.land AS Land,
meteorology.temperature,
meteorology.humidity,
WEEKOFYEAR(meteorology.date) AS Week,
YEAR(meteorology.date) AS Year,
CASE WHEN TIME(meteorology.date) >= '06:00:00'
AND TIME(meteorology.date) <= '18:00:00'
THEN 1 ELSE 0 END AS IsDay
FROM meteorology
INNER JOIN plands ON plands.id = meteorology.id_land
WHERE DATE(meteorology.date) BETWEEN '2016-09-12' AND '2016-09-23'
) AS itsownalias
GROUP BY Land,
WEEKOFYEAR(meteorology.date),
YEAR(meteorology.date)