Mysql SQL查询-仅当值在“0”范围内时获取行;“最后n个记录”;(特定记录)

Mysql SQL查询-仅当值在“0”范围内时获取行;“最后n个记录”;(特定记录),mysql,sql,Mysql,Sql,我有两张桌子,一张国家桌和一张气象桌。我想检索过去15天内没有下雨的所有国家的名称 天气表有一个名为“DayNum”的列,它从1->无穷大开始,每天增加1,这是唯一的。这个表还有一个名为“Rain”的列,它只是一个0或1的布尔值 此外,并非所有国家都是在同一天添加的,因此每个国家的最大DayNum将不同 下表示例(为了可读性,数据被截断): 国家: ID Name 1 USA 2 Cananda 3 Brazil 天气

我有两张桌子,一张国家桌和一张气象桌。我想检索过去15天内没有下雨的所有国家的名称

天气表有一个名为“DayNum”的列,它从1->无穷大开始,每天增加1,这是唯一的。这个表还有一个名为“Rain”的列,它只是一个0或1的布尔值

此外,并非所有国家都是在同一天添加的,因此每个国家的最大DayNum将不同

下表示例(为了可读性,数据被截断):

国家:

    ID     Name
     1      USA
     2      Cananda
     3      Brazil
天气

    ID    Country_id    DayNum    Rain
     1        1           1         0
     2        1           2         0
     3        1           3         1
以下是我当前的查询尝试(已为此工作了几天):

我认为这应该行得通,但我有严重的性能问题。我需要编写的实际查询处理不同的数据(相同的确切概念)和数百万行。这个查询似乎以指数速度变慢

有人能提供一些建议吗


我的另一个想法是,以某种方式限制连接仅获取前15条记录(同时按weather.day_num排序),但我还没有找到在连接中实现这一点的方法(如果可能的话)。

您对降雨量不感兴趣,只关心它是否存在,所以

select * from countries
left join
(
        select weather.country_id 
        from weather 
            inner join 
            (select country_id, MAX(daynum) as maxdaynum from weather group by country_id) maxday
                on weather.country_id = maxday.country_id
                and weather.daynum>maxday.maxdaynum-3
                where rain=1
        ) rainy
on countries.id = rainy.country_id
where country_id is null    

我认为您已经对表进行了适当的索引

您没有在表中包含任何有关索引的信息,但我敢打赌您遇到的性能问题与“国家/地区名称”字段中的group by相关。如果该列没有索引,它肯定会解释您的性能问题

话虽如此,这种情况可能需要子查询而不是内部联接。我很想这样写查询:

SELECT countries.id, countries.name 
FROM countries 
INNER JOIN 
(
    SELECT country_id 
    FROM weather 
    GROUP BY country_id 
    HAVING weather.daynum > (MAX(weather.day_num) - 15) AND SUM(weather.rain) = 0 
) AS weather
ON weather.country_id = countries.id;

也许您可以使用一个简单的变量来存储所需的min daynum?我不是mySQL开发人员,但我认为这样做可以达到以下目的:

SELECT @minDaynum := (MAX(daynum)-15) FROM weather;

SELECT DISTINCT countries.name
FROM weather
INNER JOIN countries ON weather.country_id = countries.id
WHERE
    weather.daynum >= @minDaynum AND
    weather.rain = 1;
编辑>>如果只有一个变量不适合您的情况,可以尝试使用临时表来加快速度(但不确定mysql中临时表的性能是否真的很好…:

在这里,我只是将每个国家的最小daynum存储在临时表中。希望对你有帮助

我有两张桌子,一张国家桌和一张气象桌。我想检索过去15天内没有下雨的所有国家的名称

给你:

SELECT * FROM Country
WHERE
    NOT EXISTS (
        SELECT * FROM Weather
        WHERE
            Rain = 1
            AND DayNum >= 2
            AND Country_id = Country.ID
    );
在计划英语中:对于每个国家,检查是否有比给定天数新的雨天。如果有,则从结果中删除该国家

2
替换为15天前的天数。在
{Country\u id,DayNum,Rain}
上建立索引,以获得良好的性能。不幸的是,MySQL不太可能以最佳方式执行此查询,但是只有这么多国家,所以嵌套循环应该不会太糟糕,因为DBMS应该能够以单个索引搜索的方式执行内部查询

P>可选地,考虑将它改写为连接,例如:

SELECT Country.*
FROM Country LEFT JOIN Weather
    ON Country_id = Country.ID
    AND Rain = 1
    AND DayNum >= 2
GROUP BY Country.ID, Country.Name
HAVING MAX(Rain) IS NULL OR MAX(Rain) = 0;

一个有效的SQL FIDLE示例是。

这给了我一个错误:错误1111(HY000):组函数的使用无效。我认为这是由于在WHERE子句中使用聚合函数(max,sum)而不是HAVING子句造成的?我需要熟悉declare和BEGIN…END,但我认为这不起作用,因为我所有的国家都有不同的max DayNum(我想我的示例在这个意义上有点弱)。所以我想如果美国比其他国家早15天加入,我会得到糟糕的结果。我更新了我的OP来反映这一点。我只优化了max(daynum),因为我认为它们是一样的。。。我会重新编辑的in@podiluska提出了这一点(并编辑了他们的帖子)。问题是并非每个国家的MAX(daynum)值都相同。如果他们这样做的话,这可能会起作用。
SELECT * FROM Country
WHERE
    NOT EXISTS (
        SELECT * FROM Weather
        WHERE
            Rain = 1
            AND DayNum >= 2
            AND Country_id = Country.ID
    );
SELECT Country.*
FROM Country LEFT JOIN Weather
    ON Country_id = Country.ID
    AND Rain = 1
    AND DayNum >= 2
GROUP BY Country.ID, Country.Name
HAVING MAX(Rain) IS NULL OR MAX(Rain) = 0;