Mysql 选择第一行,但仅当存在多个匹配项时?
鉴于下表“用户”:Mysql 选择第一行,但仅当存在多个匹配项时?,mysql,sql,Mysql,Sql,鉴于下表“用户”: +----+---------+--------+ | id | name | office | +----+---------+--------+ | 1 | David | 1 | | 2 | Roz | 1 | | 3 | Patrick | 2 | | 4 | Chris | 3 | | 5 | Agnes | 3 | | 6 | Freya | 3 | +----+
+----+---------+--------+
| id | name | office |
+----+---------+--------+
| 1 | David | 1 |
| 2 | Roz | 1 |
| 3 | Patrick | 2 |
| 4 | Chris | 3 |
| 5 | Agnes | 3 |
| 6 | Freya | 3 |
+----+---------+--------+
我想选择任何给定办公室的第一个用户,但前提是有多个用户,因此:
Office 1=用户1 David
办公室2=空
办公室3=用户4
大致如下:
SET @office_id = 2;
SELECT *
FROM `users`
WHERE `office` = @office_id AND number-of-users-for-office > 1
ORDER BY `id` ASC
LIMIT 1;
输出
╔════════╦════════╗
║ OFFICE ║ NAME ║
╠════════╬════════╣
║ 1 ║ David ║
║ 2 ║ (NULL) ║
║ 3 ║ Chris ║
╚════════╩════════╝
子查询的目的是为每个办公室获取最少的ID。extra HAVING子句只过滤在特定办公室中有多个员工的记录
然后,表用户通过左联接在子查询上联接,以获取表中的所有office。使用MAX或MIN对记录进行聚合,以获得每个办公室的单个记录。编辑
我想出了另一个解决方案,我正在为后代记下
-- Office id...
SET @office_id = 1;
-- Find the latest user
SELECT `id` INTO @latest_user_id
FROM `users`
WHERE `office` = @office_id
ORDER BY `id` DESC
LIMIT 1;
-- Find the first user that isn't the first
SELECT `id` INTO @latest_user_id
FROM `users`
WHERE `office` = @office_id AND `id` != @latest_user_id
ORDER BY `id` ASC
LIMIT 1;
此选项选择最新的,然后尝试选择与最新的不相同的第一个。因此,如果只有一行,您将根据需要得到NULL。我发现这种技术很容易阅读/理解;我修改了查询以满足我的需求,根据sql标准,仅查找单个办公室,从子查询返回的记录是无序的行集,即使其中包含ORDERBY子句。在您的示例中,可能是因为您只有很少的行集。但我仍然无法判断这个查询是否适用于包含数百万行的大型表。这里有人问了一个问题@oodavid,我想你误解了。只有在同一查询上使用GROUPBY子句时,ORDERBY才会无序。在我的查询中,子查询没有GROUPBY子句。我希望这将在数百万行上起作用。可能是表演matters@491243您的链接支持Shafeeq的声明,即当与GROUP BY组合时,该链接无法按预期工作。哪一个是真的?假设我在office列上有索引,您认为您的查询和下面的@Shafeeq之间会有什么样的性能差异修改为检索单个office@oodavid你想在你的最终结果中得到你的办公室和名字,还是你上面展示的只是一个例子?是的,只是一个例子;真正的问题更复杂,所以我把它提炼成一些简单的东西。实际上,我正在编写一个触发器,将我的项目自动链接到引用项目以节省开销的第一个和最后一个item_records表。我们通常想知道我们第一次记录这个项目是什么时候,最后一次记录这个项目是什么时候,但我不希望它们是相同的,因此需要检查这个项目是否有多个记录。
SELECT `office`,if(count(`id`)>1,name,'NULL') as name
FROM (SELECT * FROM `tablename` ORDER BY id ASC)
`tablename`
GROUP BY `office`
ORDER BY `id` ASC
-- Office id...
SET @office_id = 1;
-- Find the latest user
SELECT `id` INTO @latest_user_id
FROM `users`
WHERE `office` = @office_id
ORDER BY `id` DESC
LIMIT 1;
-- Find the first user that isn't the first
SELECT `id` INTO @latest_user_id
FROM `users`
WHERE `office` = @office_id AND `id` != @latest_user_id
ORDER BY `id` ASC
LIMIT 1;