仅从分组依据中选择一行?
Posted
技术标签:
【中文标题】仅从分组依据中选择一行?【英文标题】:Select only one row from a group by? 【发布时间】:2015-09-03 16:28:43 【问题描述】:我正在使用 Microsoft Access 2010,我有一个表 T_Offers
,如下所示:
Key ID Date Name Text
--- -- ---------- ----------- -----------
1 10 10/10/2015 Lorem Consectetur
2 10 10/10/2015 Ipsum Amet
3 11 27/09/2014 Dolor Sit
4 13 12/11/2013 Sit Dolor
5 14 11/07/2015 Amet Ipsum
6 14 12/07/2015 Consectetur Lorem
我只需要获取每个 ID 的一行(日期最小的那一行),因此,例如,此表的结果将是:
Key ID Date Name Text
--- -- ---------- ----------- -----------
1 10 10/10/2015 Lorem Consectetur
3 11 27/09/2014 Dolor Sit
4 13 12/11/2013 Sit Dolor
5 14 11/07/2015 Amet Ipsum
这是我尝试过的查询之一:
SELECT ID, name, text, MIN (date) AS minDate
FROM (SELECT ID, name, text, date
FROM T_Offers
GROUP BY ID, name, text, date
ORDER BY ID asc) as X
GROUP BY ID, name, text
这可以正常工作,但有一个小问题:如果 2 个具有相同 ID 的报价具有相同的日期,则结果表将重复 ID,我不希望这种情况发生。有没有办法解决这个问题?
【问题讨论】:
【参考方案1】:您可以使用NOT EXISTS
排除存在具有相同 ID 和更早日期的另一行的所有行:
SELECT t1.Key, t1.ID, t1.Date, t1.Name, t1.Text
FROM t_offers AS t1
WHERE NOT EXISTS
( SELECT 1
FROM T_Offers AS t2
WHERE t2.ID = t1.ID
AND t2.Date < t1.Date
);
这将为每个 ID 留下 1 行,它将是日期最早的行。
关于然后删除第一个日期相同的重复项,我不确定您的逻辑,但您可能需要进一步检查,这可能会变得非常混乱。在这种情况下,我使用了Key
来确定应该返回两条记录中的哪一条。
SELECT t1.Key, t1.ID, t1.Date, t1.Name, t1.Text
FROM t_offers AS t1
WHERE NOT EXISTS
( SELECT 1
FROM T_Offers AS t2
WHERE t2.ID = t2.ID
AND ( t2.Date < t1.Date
OR (t2.Date = t1.Date AND t2.Key < t1.Key)
)
);
【讨论】:
这就是答案,谢谢(无论如何我认为子查询条件 t2.ID = t2.ID 应该是 t2.ID = t1.ID 对吗?还有另一个问题:你能解释一下“SELECT 1”是什么意思? 是的,确实应该是t2.ID = t1.ID
。我已经纠正了这一点。在EXISTS
子句中,不会检索列,但您仍需要在SELECT
之后放置一些内容。对我来说SELECT 1
只是一种风格选择,其他人更喜欢SELECT NULL
或SELECT *
。我选择SELECT 1
,因为它更短,并且表明我不关心值的意图,只是存在一行。有一个related question here【参考方案2】:
假设 id 不重复,这是在 Access 中执行此操作的一种方法:
select o.*
from t_offers as o
where o.key = (select min(o2.key)
from t_offers as o2
where o2.id = o.id
);
【讨论】:
对不起,如果我现在才问,我忘了在问题中包含这个:有没有办法让每个 id 只选择 1 条记录,但日期最短? @MattiaNocerino 。 . .根据问题中的数据,看起来key
是唯一的,所以这个将每个id 只选择一条记录。【参考方案3】:
您需要一个选择不同的查询:
SELECT DISTINCT ID, name, text, MIN (date) AS minDate
FROM T_Offers
GROUP BY ID, name, text
ORDER BY ID asc;
【讨论】:
这与我已经尝试过的东西非常相似,并且给出了同样的问题:如果有 2 个具有相同 ID 和相同日期的报价,我将不会获得不同的 ID跨度> 如果它们具有相同的 id、name、text 和 date,distinct 将删除重复的行。但是,如果您有相同的 ID、相同的日期,但名称或文本不同,则不会。在这种情况下,您希望查询如何响应?如果您不关心出现的所有不同名称和文本,请不要按它们分组:SELECT DISTINCT ID, name, text, MIN (date) AS minDate FROM T_Offers GROUP BY ID ORDER BY ID asc;
【参考方案4】:
这是我的解决方案。虽然我的测试环境是mysql,但sql语法是一样的。
SELECT TO1.KEY,TO1.ID,TO.DATE,TO1.NAME,TO1.TEXT
FROM T_Offer TO1
INNER JOIN
(
select MIN(TO2.KEY) AS KEY from T_Offer TO2 group by ID
)TO3
ON TO1.KEY = TO3.KEY
建议:如果您方便的话,我可以帮助您提供创建表和插入测试数据的脚本。
【讨论】:
以上是关于仅从分组依据中选择一行?的主要内容,如果未能解决你的问题,请参考以下文章