这个答案有一些解释 - 你所追求的实际查询在底部。
这是一个实例,不仅选择每组的最大/最小字段,还选择与其对应的其他字段。
执行此操作的规范方法是通过LEFT JOIN-将表设置为自身。
例如,要选择与来自CONNECTIONS 的最新连接对应的整行,您可以:
SELECT c.userid, c.tzid as latestTZ, c.dateconn as latestConn
FROM CONNECTIONS c
LEFT JOIN CONNECTIONS c2 ON c.userid=c2.userid AND c.dateconn<c2.dateconn
WHERE c2.dateconn IS NULL
ORDER BY c.userid;
这实质上将CONNECTIONS 与userid 上的自身连接起来,并在c.dateconn<c2.dateconn 所在的用户ID 内形成每对可能的连接日期。如果c2 中没有日期大于c 的行,那么您选择了最大(即最近的)日期。
JOIN 确保您还可以从表中选择相应行的其余部分。
考虑到这一点,这就是我们为每个用户选择第一个连接日期和标签的方式(如果他们从未连接过,则使用 NULL。如果您不希望这种行为(即只显示已连接)然后您可以完全忽略USERS 表)。
SELECT u.id,c.dateconn as firstConnection,TZ.label AS firstTZ
FROM USERS u
LEFT JOIN CONNECTIONS c ON u.id=c.userid
LEFT JOIN CONNECTIONS c2 ON c.userid=c2.userid AND c.dateconn > c2.dateconn
LEFT JOIN TZ ON c.tzid=TZ.id
WHERE c2.dateconn IS NULL;
选择最新的也是一样的,只是将>反转为<:
SELECT u.id,c.dateconn as latestConnection,TZ.label AS latestTZ
FROM USERS u
LEFT JOIN CONNECTIONS c ON u.id=c.userid
LEFT JOIN CONNECTIONS c2 ON c.userid=c2.userid AND c.dateconn < c2.dateconn
LEFT JOIN TZ ON c.tzid=TZ.id
WHERE c2.dateconn IS NULL;
您的查询有点复杂,因为您不仅要选择最小值或最大值,还要选择 both 最小值 和 最大值。
解决方案
我认为您可能能够 UNION 前两个查询,或者您可以通过基本上 JOIN 将两个查询一起执行一次犯规完成所有操作:
# MIN & MAX
SELECT u.id, c.dateconn as firstCon, TZ.label as firstTZ,
c3.dateconn as latestCon, TZ2.label as latestTZ
FROM USERS u
LEFT JOIN CONNECTIONS c ON u.id=c.userid
LEFT JOIN CONNECTIONS c2 ON c.userid=c2.userid AND c.dateconn > c2.dateconn
LEFT JOIN CONNECTIONS c3 ON c.userid=c3.userid AND c3.dateconn >= c.dateconn
LEFT JOIN CONNECTIONS c4 ON c3.userid=c4.userid AND c3.dateconn < c4.dateconn
LEFT JOIN TZ ON TZ.id=c.tzid
LEFT JOIN TZ TZ2 ON TZ2.id=c3.tzid
WHERE c2.dateconn IS NULL
AND c4.dateconn IS NULL
ORDER BY u.id;
(c,c2) 对找到第一个连接日期/时区,(c3,c4) 对找到最新的。
此外,与c3 的连接实际上并不需要c3.dateconn>=c.dateconn 量词(它所需要的只是连接userid),但它额外缩小了我们必须连接的行。这是因为由于我们在 (c3,c4) 表中寻找最新(即 MAX)日期,而 c 包含 MIN 日期,我们只需要查看 MAX 日期 >= MIN 日期的行.