Mysql FROM子句中的SQL子查询

Mysql FROM子句中的SQL子查询,mysql,sql,Mysql,Sql,我发现了一些关于这个问题的问题,MySQL似乎不允许这样做。很好,我不必在FROM子句中有子查询。然而,我不知道如何避开它。以下是我的设置: 我有一个度量表,它有我想要的3列:ControllerID、TimeStamp和State。基本上,数据收集引擎每5分钟联系数据库中的每个控制器,并在度量表中粘贴一个条目。表中有这三列,加上一个我不关心的MetricsID。也许有更好的方法来存储这些指标,但我不知道。 无论如何,我想要一个视图,它为每个不同的ControllerID获取最新的时间戳,并获取

我发现了一些关于这个问题的问题,MySQL似乎不允许这样做。很好,我不必在FROM子句中有子查询。然而,我不知道如何避开它。以下是我的设置:

我有一个度量表,它有我想要的3列:ControllerID、TimeStamp和State。基本上,数据收集引擎每5分钟联系数据库中的每个控制器,并在度量表中粘贴一个条目。表中有这三列,加上一个我不关心的MetricsID。也许有更好的方法来存储这些指标,但我不知道。 无论如何,我想要一个视图,它为每个不同的ControllerID获取最新的时间戳,并获取时间戳、ControllerID和状态。因此,如果有4个控制器,则视图应始终有4行,每个行具有不同的控制器及其最新状态

我已经能够创建一个查询来获取我想要的内容,但是它依赖于FROM子句中的子查询,这在视图中是不允许的。以下是我到目前为止的情况:

SELECT *
FROM
    (SELECT 
    ControllerID, TimeStamp, State
    FROM Metrics
    ORDER BY TimeStamp DESC)
AS t
GROUP BY ControllerID;
就像我说的,这很有效。但我不能用在一个视图中。我尝试过使用max()函数,但与here一样:如果我想要除groupby和orderby列之外的任何其他列,max()就不起作用。我已经确认了这个限制,它不起作用

我还尝试将度量表更改为按时间戳排序。那也不行;保留了错误的行

编辑:这是我从中提取的度量表的
显示创建表

 CREATE TABLE Metrics (
  MetricsID int(11) NOT NULL AUTO_INCREMENT,
  ControllerID int(11) NOT NULL,
  TimeStamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  State tinyint(4) NOT NULL,
  PRIMARY KEY (MetricsID),
  KEY makeItFast (ControllerID,MetricsID),
  KEY fast (ControllerID,TimeStamp),
  KEY fast2 (MetricsID),
  KEY MetricsID (MetricsID),
  KEY TimeStamp (TimeStamp)
) ENGINE=InnoDB AUTO_INCREMENT=8958 DEFAULT CHARSET=latin1

编辑对不起,我误解了你的问题;我以为您在试图克服视图中的嵌套查询限制

您试图为每个不同的ControllerID显示最近的行。此外,您正在尝试以一个视图来执行此操作

首先,让我们开始吧。如果您的
MetricsID
列(我知道您并不关心)是一个自动增量列,那么这非常简单

SELECT ControllerId, TimeStamp, State
  FROM Metrics m
  WHERE MetricsID IN (
              SELECT MAX(MetricsID) MetricsID
                FROM Metrics
               GROUP BY ControllerID) 
  ORDER BY ControllerID 
此查询使用
MAX。。。分组依据
,为每个控制器提取编号最高(最近)的行。它可以做成一个视图

(ControllerID,MetricsID)
上的复合索引将能够高效地满足子查询

我困惑的根本原因是:我没有仔细阅读你的问题


您困惑的根本原因是:您正试图利用有害的MySQL对GroupBy的扩展。您对子查询进行排序的想法可能已经奏效。但你暂时的成功是目前实施的意外副作用。阅读以下内容:

如果您想要每个控制器的最近一行,以下内容是视图友好的:

SELECT ControllerID, TimeStamp, State
FROM Metrics m
WHERE NOT EXISTS (SELECT 1
                  FROM Metrics m2
                  WHERE m2.ControllerId = m.ControllerId and m2.Timestamp > m.TimeStamp
                 );
您的查询无论如何都是不正确的,因为它使用的MySQL扩展不能保证正常工作。
state
的值不一定来自时间戳最大的行。它来自任意一行

编辑:


为了获得最佳性能,您需要在
度量(ControllerId,Timestamp)

上建立一个索引,从查询中创建一个新表,添加一个触发器,使其在需要的时间间隔内保持更新,在视图中使用该索引不幸的是,您引用的答案不正确,因为它使用了一个明确记录的MySQL扩展来不返回查询工作所需的结果:。是的,这是MySQL的一个(奇怪的)限制:您不能在视图中使用派生表(这就是您所拥有的)。您需要重新编写语句,以避免使用派生表。嗯,它确实有效。谢谢不过我有几个问题。首先,有没有办法优化这个查询?在一个简单的mysql提示符中运行需要5秒以上的时间。第二,为什么我的初始查询不起作用?它对所有结果进行排序,然后使用group by从顶部开始(是否从顶部开始?),并选择所有不同的ControllerID。每次我测试它,它似乎都能工作。@Carrot。子查询中的排序(理论上)与
groupby
state
的值选择任意行无关。该值来自不确定的行。这意味着,
分组依据
不一定会影响它。太棒了!我想我现在明白了。但是,即使使用索引,查询仍需要3秒以上的时间才能运行。我可以做些什么来进一步优化吗?我觉得这不是一个激烈的质疑,也不应该花那么长时间。再次感谢你的帮助@胡萝卜。如果您有一个大表(有数百万行),那么在MySQL中创建一个高效的视图可能会很困难。这会引导你进入一个由触发器维护的汇总表,这很恶心。也许我只是看不到它,但我根本不明白这是如何回答这个问题的……嗯,我误解了你的问题。请看我的编辑。好的,我看看这是怎么回事。但是,运行需要9秒。。。我可以解决这个问题,但我的度量表只有约8500行。当我完成它的时候,它可能会有更多。我对查询进行了分解,每个部分都自行快速运行。示例:如果我用子查询获取所有max(MetricID),则用这些数字替换子查询
(选择…FROM…WHERE Metrics ID IN(856285675478553285688569)
,它运行得更快。这是为什么?我还能做更多的优化吗?谢谢你的帮助!很抱歉重复评论。我刚刚做了以下几点,事情似乎进展得很快。我可能做了一些非常愚蠢的事情……首先,我用子查询
选择MAX(MetricsID)创建了一个视图然后,我用以下内容创建了另一个视图:
SELECT ControllerID,TimeStamp,State FROM Metrics WHERE MetricsID IN(SELECT*FROM)
这样做有效吗?超快的查询时间可能是缓存的结果。仅子查询的性能如何