Select 一组依据只有一行?
Select only one row from a group by?
我使用的是 Microsoft Access 2010,我有一个 table 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 的一行(日期最小的那一行),因此,例如,table 的结果将是:
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 的报价具有相同的日期,结果 table 将重复 ID,我不希望这种情况发生。这个问题有替代方案吗?
假设 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
);
您需要一个 select 不同的查询:
SELECT DISTINCT ID, name, text, MIN (date) AS minDate
FROM T_Offers
GROUP BY ID, name, text
ORDER BY ID asc;
您可以使用 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)
)
);
这是我的solution.Althouth我的测试环境是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
建议:如果方便的话,我帮你提供创建table和插入测试数据的脚本。
我使用的是 Microsoft Access 2010,我有一个 table 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 的一行(日期最小的那一行),因此,例如,table 的结果将是:
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 的报价具有相同的日期,结果 table 将重复 ID,我不希望这种情况发生。这个问题有替代方案吗?
假设 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
);
您需要一个 select 不同的查询:
SELECT DISTINCT ID, name, text, MIN (date) AS minDate
FROM T_Offers
GROUP BY ID, name, text
ORDER BY ID asc;
您可以使用 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)
)
);
这是我的solution.Althouth我的测试环境是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
建议:如果方便的话,我帮你提供创建table和插入测试数据的脚本。