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;