dgi*_*gig 1 mysql join max min
我知道这是一个常见的问题,因为我之前已经问过它,并且已经看了几个,但是,尽管我的查询基于此,但我无法让它发挥作用.见:Mysql的联接基于MAX(时间戳)和MySQL的左连接右表最大值
基本上我有一个不同项目的表格('椅子','桌子'),每种类型的记录都有自己的特定椅子或桌子的id.然后我有一个位置表,它保留了所有曾经存在的位置,包括当前位置.当前位置由MAX时间戳记记.
我的查询是为了获取所有项目,并加入到当前位置.我已经按照其他人所说的工作,但这对我不起作用.任何帮助表示赞赏.
编辑:我没有说它是如何失败的:它获取记录并进行连接,它返回最大时间戳,但不返回与MAX(时间戳)记录对应的记录信息.因此它给出了正确的时间戳,但是地板等不是来自具有MAX时间戳的记录.
谢谢!
查询:
$q = "SELECT
'chairs' AS work_type,
chairs.id AS work_id,
chairs.title,
chairs.dimensions,
CurrentLocations.floor,
CurrentLocations.bin,
CurrentLocations.bay,
CurrentLocations.other
FROM chairs
LEFT JOIN (
SELECT
locations.id AS loc_id,
locations.work_type AS clwt,
locations.work_id AS clwi,
locations.floor,
locations.bin,
locations.bay,
locations.other,
MAX(locations.timestamp) AS latestLocation
FROM
locations
GROUP BY
locations.work_type, locations.work_id
) CurrentLocations
ON CurrentLocations.clwi = chairs.id AND CurrentLocations.clwt = 'chairs'
WHERE cur_loc LIKE '%19th Street%'
ORDER BY
FIELD(floor, 'Basement', '3rd Floor', '4th Floor', '5th Floor'),
bin,
bay,
other";
Run Code Online (Sandbox Code Playgroud)
试试这个:
SELECT
'chairs' AS work_type, -- do you really need this in the result?
c.id AS work_id,
c.title,
c.dimensions,
l.floor,
l.bin,
l.bay,
l.other
FROM
chairs AS c
LEFT JOIN
( SELECT work_id,
MAX(timestamp) AS latestLocation
FROM locations
WHERE work_type = 'chairs'
GROUP BY work_id
) AS cl -- CurrentLocations
ON cl.work_id = c.id
LEFT JOIN
locations AS l
ON l.work_type = 'chairs'
AND l.work_id = cl.work_id
AND l.timestamp = cl.latestLocation
WHERE
c.cur_loc LIKE '%19th Street%'
ORDER BY
FIELD(l.floor, 'Basement', '3rd Floor', '4th Floor', '5th Floor'),
l.bin,
l.bay,
l.other ;
Run Code Online (Sandbox Code Playgroud)
描述:
你要:
基本上我有一个不同项目(
chairs,tables)的表格,每种类型的记录都有自己的特定椅子或桌子的ID.然后我有一张locations桌子可以保存所有曾经存在的位置,包括当前位置.当前位置以最大值表示timestamp.我的查询是为了获取所有项目(椅子),并加入到当前位置.
因此,对于每个项目(即a chair),您只需要最新的项目 location.对于work_id表中的每一个location,你想要的MAX(timestamp).GROUP BY正如您已经发现的那样,这很容易找到:
( SELECT work_id,
MAX(timestamp) AS latestLocation
FROM locations
GROUP BY work_type
, work_id
) AS cl
Run Code Online (Sandbox Code Playgroud)
但是,您还希望使用该表中的其他列,如果只是将它们添加到选择列表中,则会显示错误的结果.(注意,在大多数DBMS,为了使用不在列GROUP BY列表中,你必须申请一个聚集功能,如适用你MAX()来timestamp.MySQL允许这种行为,如果使用得当,可以有一些好处,但它没有实现它100%防故障,因此在某些情况下应用它,像这样,可能会给出错误的结果.Postgres有一个更好的实现这个功能,它不会允许错误的结果.)
因此,您需要做的是使用上面的GROUP BY查询作为派生表(您可以将其命名,cl或者CurrentLocation,无论您想要什么)并locations使用GROUP BY列表中的所有列和聚合的(timestamp)将其连接到表:
JOIN
locations AS l
ON l.work_type = cl.work_type
AND l.work_id = cl.work_id
AND l.timestamp = cl.latestLocation
Run Code Online (Sandbox Code Playgroud)
之后,您可以chairs照常将他们加入到桌子中.既然,你chairs LEFT JOIN locations在原始查询中有一个,我也将这些保留在答案中.
另一个小修改是,既然你有CurrentLocations.work_id = 'chairs',你只想要locations表中的那些行.因此,首先进行分组然后拒绝所有与该条件不匹配的行是相当多余的.首先应用条件然后分组可能更有效.最终的分组查询和连接条件会相应地进行修改.
另请注意,索引(work_type, work_id, timestamp)将提高查询的效率(cl子查询将仅JOIN locations使用该索引进行处理,并且也将使用索引来定位位置表中所需的行.)