【问题标题】:SQL: How to find min value per group in sql?SQL:如何在 sql 中找到每组的最小值?
【发布时间】:2018-03-04 00:29:23
【问题描述】:

我有下表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

【问题讨论】:

  • 您使用的是 MySQL 还是 SQL Server?
  • 您需要将它们视为连接后的日期并应用 MIN 函数。
  • @GiorgosBetsos MySQL
  • 如果您可以将date 数据存储在date 类型列中,而不是分隔列...
  • 没有串联的任何其他方式吗?

标签: mysql sql


【解决方案1】:

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

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

尚未对此进行测试,但这应该会给您一个想法。

【讨论】:

    【解决方案2】:

    您可以连接日期字段中的值,将它们转换为日期并选择最小日期(在这种情况下,我希望值是 varchar):

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

    【讨论】:

    • 谢谢!串联确实简化了它。
    【解决方案3】:

    在 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;
    

    【讨论】:

      【解决方案4】:

      可能有更简单的解决方案,但您可以从年、月和日三列中创建一个新的日期类型列。然后得到最小日期如下:

      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;
      

      demo

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

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

      【讨论】:

        【解决方案5】:

        你能试试这个,如果它在没有连接的情况下解决你的问题,请告诉我?如有必要,可以通过子查询变得更加健壮。

        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`;
        

        谢谢,

        詹姆斯

        【讨论】:

          【解决方案6】:

          你可以试试排名函数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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-07-11
            • 1970-01-01
            • 2017-08-01
            • 2013-09-07
            • 2022-10-05
            • 2020-11-06
            相关资源
            最近更新 更多