mysql SQL:如何在SQL中找到每个组的最小值?

h5qlskok  于 2023-03-22  发布在  Mysql
关注(0)|答案(7)|浏览(202)

下面是snapshots

domain      year  month  day
---         ---    ---   ---
google      2007   04    15
google      2005   08    31
google      2005   12    01
facebook    2006   04    15
facebook    2006   02    25
facebook    2008   01    01

我想检索的是每个域的第一个(最早)日期。
因此输出应为:

google    2005  08  31
facebook  2006  02  25

我尝试了以下查询,但它检索每列的最小值:

select domain, min(year), min(month), min(day) from snapshots group by domain
j1dl9f46

j1dl9f461#

如前所述,您应该使用串联来创建单个日期,然后选择最小值。

select domain, MIN(CAST(CONCAT(`year`, '-'`,month`,'-',`day`) AS DATE)) from snapshots group by domain

我没有测试过这个,但这应该给予你一个想法。

wztqucjr

wztqucjr2#

您可以连接date字段中的值,将它们转换为date并选择最小日期(在本例中,我希望值为varchar):

SELECT domain, 
MIN(CAST(CONCAT(year,'-',month,'-',day) AS date)) 
FROM snapshots 
GROUP BY domain;
xxls0lw8

xxls0lw83#

在MySQL中:

SELECT
    domain,
    FROM_UNIXTIME(UNIX_TIMESTAMP(MIN(CONCAT(year,'-',month,'-',day))), '%Y') as y,
    FROM_UNIXTIME(UNIX_TIMESTAMP(MIN(CONCAT(year,'-',month,'-',day))), '%m') as m,
    FROM_UNIXTIME(UNIX_TIMESTAMP(MIN(CONCAT(year,'-',month,'-',day))), '%d') as d
FROM snapshots
GROUP BY domain;
mlmc2os5

mlmc2os54#

可能有更简单的解决方案,但您可以从三列year,month和day中创建一个新的日期类型列。然后按以下方式获取min date:

SELECT DISTINCT s.domain, s.year, s.month, s.day
FROM
(
  SELECT domain, year,month,day,
       STR_TO_DATE(CONCAT(`year`,'-',LPAD(`month`,2,'00'),'-',LPAD(`day`,2,'00')) ,'%Y-%m-%d') AS FullDate
    FROM snapshots
) AS s
INNER JOIN
(
  SELECT domain, MIN(Fulldate) MinDate
  FROM
  (
    SELECT domain, year,month,day,
       STR_TO_DATE(CONCAT(`year`,'-',LPAD(`month`,2,'00'),'-',LPAD(`day`,2,'00')) ,'%Y-%m-%d') AS FullDate
    FROM snapshots
  ) AS t
  GROUP BY domain
) AS t  ON t.MinDate = s.FullDate 
       AND t.Domain = s.Domain;

演示
这将为您提供您想要的确切结果:

|   domain | year | month | day |    MinDate |
|----------|------|-------|-----|------------|
|   google | 2005 |     8 |  31 | 2005-08-31 |
| facebook | 2006 |     2 |  25 | 2006-02-25 |
polhcujo

polhcujo5#

你能试一下这个吗?如果没有连接,它是否能解决你的问题?如果需要的话,可以通过子查询来使它更健壮。

CREATE TABLE domainDate(domain CHAR(25), `year` INT, `month` INT, `day` INT);

INSERT INTO domainDate VALUES
    ('google', 2007, 04, 15),
    ('google', 2005, 08, 31),
    ('google', 2005, 12, 01),
    ('facebook', 2006, 04, 15),
    ('facebook', 2006, 02, 25),
    ('facebook', 2008, 01, 01);

SET @VDomain := '';
SELECT domain, `year`, `month`, `day` FROM domainDate HAVING @VDomain != @VDomain := domain ORDER BY domain, `year` * 10000 + `month` * 100 + `day`;

谢谢你,
詹姆斯

aelbi1ox

aelbi1ox6#

您可以尝试使用排名函数ROW_NUMBER()

CREATE TABLE domainDate(domain CHAR(25), [year] INT, [month] INT, [day] INT);

INSERT INTO domainDate VALUES
    ('google', 2007, 04, 15),
    ('google', 2005, 08, 31),
    ('google', 2005, 12, 01),
    ('facebook', 2006, 04, 15),
    ('facebook', 2006, 02, 25),
    ('facebook', 2008, 01, 01);

SELECT domain
    ,[year]
    ,[month]
    ,[day]
FROM 
(
    SELECT domain
        ,[year]
        ,[month]
        ,[day]
        ,ROW_NUMBER() OVER(PARTITION BY domain ORDER BY [year], [month], [day]) AS RN
    FROM domainDate
) t
WHERE RN = 1
rryofs0p

rryofs0p7#

在MS SQL中,你可以这样做:

SELECT TOP 1 WITH TIES * FROM  mytable
ORDER BY row_number() OVER (PARTITION BY domain Order by year DESC, month DESC, day DESC).

详情请参阅此fiddle-link:http://sqlfiddle.com/#!18/7ad785/9

相关问题