我有一个我想要实现的查询,并且有一些不太正确。
以下是表格的基础知识(我遗漏了不必要的东西以及索引和外键的东西):
CREATE TABLE IF NOT EXISTS `PROJECT` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`USER_ID` INT NULL ,
`NAME` VARCHAR(40) NOT NULL ,
`PROJECT_NUMBER` VARCHAR(30) NULL ,
`CREATION_DATE` DATETIME NULL
CREATE TABLE IF NOT EXISTS `MODEL` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`PROJECT_ID` INT NOT NULL ,
CREATE TABLE IF NOT EXISTS `SIMULATION_SET` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`MODEL_ID` INT NULL ,
`CREATION_DATE` DATETIME NULL ,
`START_TIME` DATETIME NULL ,
`END_TIME` DATETIME NULL
我想要做的是:我想获得具有针对特定用户的最新模拟集的项目。这是一个查询示例:
SELECT P.ID, P.USER_ID, P.NAME, P.PROJECT_NUMBER, S.ID SET_ID, S.START_TIME
FROM PROJECT P
INNER JOIN MODEL M ON M.PROJECT_ID=P.ID
INNER JOIN SIMULATION_SET S ON S.MODEL_ID=M.ID
WHERE P.USER_ID=5 AND S.START_TIME IS NOT NULL
GROUP BY P.ID
ORDER BY S.START_TIME DESC LIMIT 5
我尝试了很多变种,问题是group by似乎过滤了它,这样我就可以在表中为每个项目获取第一个simulation_set,而我希望它排序的是最后一个。如果没有GROUP BY,我会获得用户所有模拟集的列表,并正确排序。我想要的是那个顺序的项目,但我不明白。
在没有分组的样本集上,我得到了这个,这是正确排序的:
+----+---------+-----------------+----------------+--------+---------------------+
| id | user_id | name | project_number | SET_ID | start_time |
+----+---------+-----------------+----------------+--------+---------------------+
| 14 | 5 | Krusty Krab | 123 | 267 | 2011-07-07 14:57:15 |
| 16 | 5 | Pineapple | p456 | 266 | 2011-07-07 12:48:58 |
| 21 | 5 | Patrick's House | US | 265 | 2011-07-07 12:48:18 |
| 14 | 5 | Krusty Krab | 123 | 264 | 2011-07-07 12:47:42 |
| 13 | 5 | Bikini Bottom | B123 | 263 | 2011-07-07 12:44:07 |
| 16 | 5 | Pineapple | p456 | 262 | 2011-07-07 12:42:52 |
| 14 | 5 | Krusty Krab | 123 | 261 | 2011-07-07 12:41:52 |
| 16 | 5 | Pineapple | p456 | 260 | 2011-07-07 12:40:21 |
+----+---------+-----------------+----------------+--------+---------------------+
使用GROUP BY子句,我得到了:
+----+---------+-----------------+----------------+--------+---------------------+
| id | user_id | name | project_number | SET_ID | start_time |
+----+---------+-----------------+----------------+--------+---------------------+
| 21 | 5 | Patrick's House | US | 265 | 2011-07-07 12:48:18 |
| 13 | 5 | Bikini Bottom | B123 | 263 | 2011-07-07 12:44:07 |
| 14 | 5 | Krusty Krab | 123 | 261 | 2011-07-07 12:41:52 |
| 16 | 5 | Pineapple | p456 | 260 | 2011-07-07 12:40:21 |
+----+---------+-----------------+----------------+--------+---------------------+
顺序错了,它从最早开始拉动start_time,而我想从最新订购。列表中的第一个项目应该是Krusty Krab。我以为我可能需要做子查询才能做到这一点,但我不确定如何做。我知道SQL向导会发现这很明显,或者至少我希望如此!在此先感谢任何帮助。
答案 0 :(得分:0)
对不起,我第一次太快回答,不太清楚,也有点不对劲...... 这是一个应该做你想要的SQL:
SELECT P.ID, P.USER_ID, P.NAME, P.PROJECT_NUMBER, S.ID SET_ID, S.START_TIME
FROM PROJECT P
INNER JOIN
(SELECT P.ID, MAX(S.START_TIME) as MAX_TIME
FROM PROJECT P
INNER JOIN MODEL M ON M.PROJECT_ID=P.ID
INNER JOIN SIMULATION_SET S ON S.MODEL_ID=M.ID
WHERE P.USER_ID=5 AND S.START_TIME IS NOT NULL
GROUP BY P.ID) PMAX ON P.ID = PMAX.ID
INNER JOIN MODEL M ON M.PROJECT_ID=P.ID
INNER JOIN SIMULATION_SET S ON S.MODEL_ID=M.ID
AND S.START_TIME = PMAX.MAX_TIME
ORDER BY S.START_TIME DESC LIMIT 5
一些注意事项:
内部SELECT的唯一目的是获得每个项目的最大开始时间。
外部选择再次执行必要的连接以查找设置ID。
(如果您在select中不需要SET_ID
,则可以删除MODEL
和SIMULATION_SET
的外部联接
没有办法(我能想到)从内部联接中获取SET_ID
,因为您按项目ID进行聚合,可以包含多个集合。
另外需要注意的是,外部选择中不需要WHERE
子句,因为项目已经过滤,只包含USER_ID = 5
的项目。
我希望这更有意义......
答案 1 :(得分:0)
我不知道您使用的是哪个数据库,但在您的请求中,我似乎很难按ID分组,并且不会聚合其他结果......
即使id是主键,在我们工作的Oracle上似乎也不允许这样做......
无论如何,你按照项目ID进行分组,好吧,但是你应该获得的结果可以链接到多个模拟集。
考虑到当你按项目分组时,你只为每个项目显示一行,因为它有多个模拟值,db应该如何知道要放在该行中的内容?这就是为什么你必须聚合不属于该组的结果...但在你的情况下,这不会很好,因为多个aggretates没有链接在一起。在开始时使用MAX将显示每个项目的最大开始时间,但您将无法检索与给定项目的最大开始时间相关的正确名称。
除了使用其他已经说过的
之类的子选择外,我没有看到任何其他内容