我需要MySQL查询的帮助。基本上是为了简化它:
我有一张桌子上有来自气候变化的气象资料。其中一个测量参数是降雨量。我已经设法将计算结果放在一个表格中,其中有一列有日(2月1日,2月2日,2月3日等)和第二列,它给出了该特定日的每日降雨量(0,3.5,14.2等)。 )。
现在我想做的是计算最长的干燥和最长的潮湿时期。换句话说,连续几天降雨量为0的最长时期,湿期是完全相反的 - 大多数连续的“非零”天。
在我想要的输出中 - 期间的天数,开始日期和结束日期。所以基本上两个变量,比如说dry_count,dry_date,然后我会转换成输出,例如:“天数:dry_count,dry_date”。
我最初将它作为两个变量(dry_start和dry_end),但是没有用,因为如果有两个例子,例如存在相同的最长周期,我会想要它,例如。 2月3日 - 2月5日,3月8日 - 3月11日 - 所以日期需要最后保存为一个变量,如果它不为空,那么它将添加一个逗号和另一个句号。
我尝试了各种各样的东西,但没有成功。数据是从MySQL数据库的PHP站点上提取的,所以我得到的结果是一行一行的。有什么帮助吗?我希望我解释好了。
答案 0 :(得分:2)
如果我理解正确的话,你会尝试将关于潮湿时期和干燥时期的新数据保存回行中,以备日后使用?
我认为这是因为随着每个新的一天被添加,很容易重新计算....或者因为数据正在移动到其他地方?
无论如何,如果是这种情况,那么你可以采用的方法就是有两个新列:'wet_count'和“dry_count”。计算每一行。如果行的湿/干值与前一天,然后递增该值。如果没有,则将值归零并将适当的值设置为新值。如下:
day rainfall wet_count dry_count
Feb 1 1 1 0
Feb 2 0.5 2 0
Feb 3 0.75 3 0
Feb 4 0 0 1
Feb 5 0 0 2
Feb 6 0 0 3
Feb 7 0.5 1 0
Feb 8 1.25 2 0
Feb 9 1.5 3 0
Feb 10 3.5 4 0
Feb 11 4.5 5 0
然后你可以简单地从表格中拉出最大值,回到该日期之前该列中的前1位,然后你就拥有了“最大的时期”和“当它开始时”。
在每个新的一天的数据中,您只需要计算前一天的数据,然后运行两个非常简单的数据库搜索以获得新的“最大期限”。
更具体地说 - 你拉出'wet_count'的明确值,按降序排序,只取第一个答案。您在数据库中执行选择,其中所有wet_count =最大值或1.并且您获得与该特定值匹配的潮湿期数加上可能的开始日期。紧接最大值之前的1将是开始日期。
答案 1 :(得分:1)
我认为相关子查询为MySQL提供了这类问题的最佳方法。这个想法是在没有下雨的一天之后找到第一天下雨,并将其用于分组目的。然后该组的最小值和最大值提供干咒的边界。
这是一个想法:
select min(date) as FirstDate, max(date) as LastDate,
(max(date) - min(date) + 1) as DrySpellDays
from (select t.*,
(select date
from t t2
where t2.rainfall > 0 and
t2.date > t.date
order by t2.date desc
limit 1
) as NextRainDate
from t
where t.rainfall = 0
) t
group by NextRainDate
连续潮湿天数的计算遵循相同的结构,但逻辑相反:
select min(date) as FirstDate, max(date) as LastDate,
(max(date) - min(date) + 1) as DrySpellDays,
sum(t.rainfall) as TotalRainFall
from (select t.*,
(select date
from t t2
where t2.rainfall = 0 and
t2.date > t.date
order by t2.date desc
limit 1
) as NextDryDate
from t
where t.rainfall > 0
) t
group by NextDryDate
答案 2 :(得分:0)
这是一个PHP未经优化的尝试。注意:这是未经测试的,我只是在这里输入,没有任何东西可以测试,没有纸张重新考虑这个做得更好,所以可能有很多改进。
$dry_date = NULL;
$dry_length = 0;
$wet_date = NULL;
$wet_length = 0;
$current_date = NULL;
$current_length = 0;
$dry_flip = false;
$wet_flip = false;
// assume you get "select date, rainfall from rainfalltable"
while($row = mysqli_fetch_array($result)) {
// if rainfall is zero we do dry_day calculation
if ($row['rainfall'] == 0) {
// two options here - we already started counting or this is a new streak of dry days
if ($dry_flip) {
// if we already started, it's simple
$current_length = $current_length +1;
} else {
// if we didn't start counting, let's reset the counter.
if ($wet_flip) {
// First check the wet status - maybe we were counting it so let's save
$wet_flip = false;
if ($current_length > $wet_length) {
// since we got the longer streak, we update wet status
$wet_date = $current_date;
$wet_length = $current_length;
}
$current_date = NULL;
$current_length = 0;
}
$current_length = $current_length + 1;
// One more thing to do
if ($current_length == 1) {
$current_date = $row['date'];
}
}
} else {
// two options here - we already started counting or this is a new streak of dry days
if ($wet_flip) {
// if we already started, it's simple
$current_length = $current_length +1;
} else {
// if we didn't start counting, let's reset the counter.
if ($dry_flip) {
// First check the wet status - maybe we were counting it so let's save
$dry_flip = false;
if ($current_length > $wet_length) {
// since we got the longer streak, we update wet status
$dry_date = $current_date;
$dry_length = $current_length;
}
$current_date = NULL;
$current_length = 0;
}
$current_length = $current_length + 1;
// One more thing to do
if ($current_length == 1) {
$current_date = $row['date'];
}
}
}
}