这是我的问题。
我在SQL查询方面不是很好,所以我希望能够深入了解LIMIT子句的不同行为。我有两个问题。让我们说我的桌子有3列,name
,date
和date_modified
。我每小时修改一次表格并使用date_modified
列对其进行修订。我正在尝试获取特定日期2017-12-12
修改日期的最后一条记录(最近修改过)。
SELECT * from
(SELECT * from table where name in ('name1','name2','name3')
and date in ('2017-12-12') order by date_modified desc)
as tmp_table group by name
SELECT * from
(SELECT * from table where name in ('name1','name2','name3')
and date in ('2017-12-12') order by date_modified desc LIMIT 100)
as tmp_table group by name
第一个返回一个表,其中修改的日期是当天最早的记录。第二个是我想要的,它返回最新修改的数据。如果我有一个更大的表,其中name3
是第101个记录,查询将无法正常工作。所以对LIMIT进行硬编码既不可行又不好。
为什么会有区别?订单是否在子查询中不起作用?
*我只是在添加其他信息,因为我自己想到了一个解决方案。
添加:上面的子查询具有相同的行为;即根据修改的日期按降序对数据进行排序。
date_modified
和date
都是日期时间格式。
表是一组无序数据。对于派生表,即子查询,情况也是如此。
第一个查询
您从表中选择某些记录并对其进行排序。 DBMS可以完全忽略这个ORDER BY
子句,因为您只将数据用作子查询。
然后按名称分组。现在我们必须区分两种情况:
name
+ date
在表中是独一无二的。然后你准确地返回你找到的行。 GROUP BY
条款将是多余的。name
+ date
在表中并不是唯一的。但你select *
。这是无效的SQL,因为如果您有一个名称和日期的多行,则不会告诉DBMS要选择哪些值。如果MariaDB让这个失败,那就是DBMS中的一个缺陷。根据您的描述,似乎第二种情况适用。您的查询无效。
第二个查询
您可以从表中选择某些记录并对其进行排序,以便应用LIMIT
子句。这限制了结果,但DBMS可以自由地以任何顺序输出行,因为您将数据用作子查询。当您通过date_modified
订购时,您可以从结果中丢弃一些名称(例如,所有name1和name2的最后一百条记录,当然您将解雇name3。
至于GROUP BY name
:关于第一个查询,我所说的内容也适用于此。您将数据限制为100行没有任何区别。
这不是你问题的真正答案。请参阅我的其他答案,了解您的查询有什么问题以及您对其行为的假设。
我想你想要的是这个,2017年12月12日每个名字的最新条目:
select *
from
(
select
t.*,
max(date_modified) over (partition by name) as max_date_modified
from t
where name in ('name1', 'name2', 'name3')
and date in (date '2017-12-12')
) numbered
where date_modified = max_date_modified
order by name;
更新:似乎MariaDB还不支持MAX OVER
(https://mariadb.com/kb/en/library/aggregate-functions-as-window-functions/)。所以使用ROW_NUMBER
代替:
select *
from
(
select
t.*,
row_number() over (partition by Name order by date_modified desc) as rn
from t
where name in ('name1', 'name2', 'name3')
and date in (date '2017-12-12')
) numbered
where rn = 1
order by name;