1

我在 MySQL 中有这三个表:

+----------------------------------------------+
| ComputerConfigs                              |
+----------+-----------------------------------+
| ConfigID | ComputerID | LastChangeDate | ... |
+----------+-----------------------------------+

+-------------------+
| Software          |
+------------+------+
| SoftwareID | Name |
+------------+------+

+-----------------------------------------------------+
| ComputerHasSoftware                                 |
+------------+----------------------------------------+
| ComputerID | ConfigID | SoftwareID | LastChangeDate |
+------------+----------------------------------------+

每次,一个 ComputerConfig 改变,都会有一个新的行写入ComputerConfigs. 所以我也能看到过去的所有变化。

现在我也在尝试跟踪软件的变化。这不会经常发生,所以我只想将新行保存到ComputerHasSoftware表中,如果有人真的添加或删除了某些东西。

我想写一个查询,它返回所有ComputerConfigs(从过去到现在)已安装的软件因此,如果没有添加一行到ComputerHasSoftware属于 a ComputerConfig,那么它应该在 ComputerConfig 的时间戳之前取最新的一行。

我想过做一个这样的查询,它只是将三个表相互连接:

SELECT 
FROM ComputerConfigs
LEFT OUTER JOIN ComputerHasSoftware
             ON ComputerHasSoftware.ComputerID = ComputerConfigs.ComputerID
LEFT OUTER JOIN Software
             ON Software.SoftwareID = ComputerHasSoftware.ComputerID

但正如您可以想象的那样,这个查询会导致错误的结果,因为它将旧软件与不属于那里的计算机相关联。将连接条件更改为ComputerHasSoftware.ConfigID = ComputerConfigs.ConfigID也不起作用,因为它会错过没有提供数据的那些,而是应该回退到最新的可用条件。

如何修改我的查询以实现这一目标?或者使用子查询是否有更好的解决方案?

4

2 回答 2

1

MySQL可以用来加快速度的技巧是有限的。使用相关的子查询起作用,但您需要检查性能。

SELECT
  *
FROM
  ComputerConfigs
LEFT OUTER JOIN
  ComputerHasSoftware
    ON ComputerHasSoftware.ComputerID = ComputerConfigs.ComputerID
    AND ComputerHasSoftware.LastChangeDate = (
                                              SELECT MAX(LastChangeDate)
                                                FROM ComputerHasSoftware
                                               WHERE ComputerID = ComputerConfigs.ComputerID
                                                 AND LastChangeDate <= ComputerConfigs.LastChangeDate
                                             )
LEFT OUTER JOIN
  Software
    ON Software.SoftwareID = ComputerHasSoftware.ComputerID 
于 2012-05-09T17:32:09.260 回答
0

您需要选择间隔日期期间:

select 
   ConfigID
  ,f.LastChangeDate as fromDate
  ,coalesce( min( t.LastChangeDate ), now() ) as toDate
from 
  ComputerConfigs f
     left outer join
  ComputerConfigs t 
    on f.ComputerID = t.ComputerID
where
  t.LastChangeDate > f.LastChangeDate
group by 
  ConfigID, f.LastChangeDate

然后以这种方式加入它:

SELECT *
FROM ComputerConfigs
LEFT OUTER JOIN ComputerHasSoftware
             ON ComputerHasSoftware.ComputerID = ComputerConfigs.ComputerID
LEFT OUTER JOIN ( above subquery) S
             ON S.ConfigID = ComputerConfigs.ConfigID
LEFT OUTER JOIN Software
             ON Software.ComputerID = ComputerHasSoftware.ComputerID and
                Software.LastChangeDate between S.fromDate and S.toDate

请注意,您应该替换above subquery为我的第一个查询。在您的问题中,我不明白您是否需要between条件<>条件。可以根据您的需求自由调整查询。享受。

于 2012-05-09T17:39:57.250 回答