为什么我从查询和视图中得到不同的结果

mar*_*net 2 mysql view group-by greatest-n-per-group

我面临的基本问题是我需要每个项目的最新记录。

一些设置... MySQL 5.6.14。

我需要创建两个视图(因为 MySQL 不允许我在视图中有子查询)。我的第一个查询设置了这样的数据。

select 
    `inventoryrecords`.`inventoryrecordid` AS `inventoryrecordid`,
    `inventoryrecords`.`logicaldeviceid` AS `logicaldeviceid`,
    `inventoryrecords`.`passrfid` AS `passrfid`,
    `inventoryrecords`.`tagepc` AS `tagepc`,
    `inventoryrecords`.`currentstate` AS `currentstate`,
    `inventoryrecords`.`statedateutc` AS `statedateutc`,
    `inventoryrecords`.`ownerobjectid` AS `ownerobjectid`,
    `inventoryrecords`.`ownerobjecttype` AS `ownerobjecttype`
from
    `inventoryrecords`
where
    1
order by `inventoryrecords`.`statedateutc` desc
Run Code Online (Sandbox Code Playgroud)

然后我可以使用我的“真实”查询将所有内容限制为每个 TagEPC 的最后一条记录。

select 
    `lastinventoryrecords_step1`.`inventoryrecordid` AS `inventoryrecordid`,
    `lastinventoryrecords_step1`.`logicaldeviceid` AS `logicaldeviceid`,
    `lastinventoryrecords_step1`.`passrfid` AS `passrfid`,
    `lastinventoryrecords_step1`.`tagepc` AS `tagepc`,
    `lastinventoryrecords_step1`.`currentstate` AS `currentstate`,
    `lastinventoryrecords_step1`.`statedateutc` AS `statedateutc`,
    `lastinventoryrecords_step1`.`ownerobjectid` AS `ownerobjectid`,
    `lastinventoryrecords_step1`.`ownerobjecttype` AS `ownerobjecttype`
from
    `lastinventoryrecords_step1`
group by `lastinventoryrecords_step1`.`tagepc`
order by `lastinventoryrecords_step1`.`statedateutc` desc
Run Code Online (Sandbox Code Playgroud)

当我尝试从“真实”视图中选择 * 时,我没有得到我期望的数据。但是,当我在窗口中使用子查询运行查询时。

select * from ( 
lastinventoryrecords_step1 )
group by tagepc
order by statedateutc desc
Run Code Online (Sandbox Code Playgroud)

产生不正确的数据,而

select * from (
    select 
        inventoryrecordid,
        logicaldeviceid,
        passrfid,
        tagepc,
        currentstate,
        statedateutc,
        ownerobjectid,
        ownerobjecttype
    from
        inventoryrecords
    where
        1
    order by statedateutc desc ) as t1
group by tagepc
order by statedateutc desc
Run Code Online (Sandbox Code Playgroud)

产生正确的数据。

这到底是怎么回事?我错过了什么?

Bil*_*win 5

您以不确定的方式使用 GROUP BY。You GROUP BY tagepc,但是您期望其他列的值是多少?

MySQL 允许这种查询,但 MySQL 从组中任意选择一行。实际上,它往往是组中的第一行,因为它们是物理存储的。

但是在您通过视图查询的情况下,视图将其结果存储在临时表中,其物理顺序可能与原始表中的数据不同。

请注意,http : //dev.mysql.com/doc/refman/5.6/en/create-view.html说:

ORDER BY在视图定义中是允许的,但如果您使用具有自己的ORDER BY.

因此,由视图运行以填充临时表的查询会忽略您视图的ORDER BY,并且由于您使用了GROUP BY它,它可能会从基础表中的任意行中获取值。

如何解决这个问题?停止运行不明确的GROUP BY查询。在您的选择列表中引用的任何列都应该由 (a) 在GROUP BY子句中列出,或 (b) 在诸如之类的分组函数中MAX()

我不知道你希望这个查询做什么,或者你为什么首先使用GROUP BY。所以我不能提供任何更具体的建议。


回复您的评论:

感谢您的澄清。这是一种非常常见的 SQL 问题。我在 StackOverflow 上创建了标签,现在它有近一千个问题。该标签存在于 dba.stackexchange.com 上,但到目前为止问题较少。

这是一个解决方案:

SELECT i.*
FROM inventoryrecords AS i
JOIN (SELECT TagEPC, MAX(StateDateUTC) AS StateDateUTC
      FROM inventoryrecords
      GROUP BY TagEPC ORDER BY NULL) AS maxi USING (TagEPC, StateDateUTC);
Run Code Online (Sandbox Code Playgroud)