【问题标题】:SQL Server: select distinct mon-yyyy format output sorty by descending orderSQL Server:选择不同的mon-yyyy格式输出按降序排序
【发布时间】:2011-08-15 22:02:36
【问题描述】:

我的表中有datetime 列,其中包含以下数据:

2011-03-23
2011-04-19
2011-04-26
2011-05-26

我想选择不同的mon-yyyy 格式输出,按报告日期降序排列。我们只需要在 SQL 语句中选择一列

此 SQL 有效,但我想按 ReportDate 列排序

SELECT  distinct SUBSTRING (convert(varchar, ReportDate, 100),1,3) +'-'+
        SUBSTRING (convert(varchar, ReportDate, 100),8,4 ) 
  FROM [EnvelopsDB].[dbo].[Envelopes]

输出

Apr-2011
Mar-2011
May-2011

此 SQL 给出错误:

SELECT  distinct SUBSTRING (convert(varchar, ReportDate, 100),1,3) +'-'+
        SUBSTRING (convert(varchar, ReportDate, 100),8,4 ) 
  FROM [EnvelopsDB].[dbo].[Envelopes]
  order by ReportDate

错误:

消息 145,第 15 级,状态 1,第 2 行
如果 SELECT DISTINCT 是 ORDER BY 项目必须出现在选择列表中 指定。

获得所需输出的最佳 SQL 查询是什么?

【问题讨论】:

    标签: sql sql-server-2008


    【解决方案1】:
    with testdata as
    (
      select cast('2011-03-23' as datetime) as d
    union all
      select cast('2011-04-19' as datetime)
    union all
      select cast('2011-04-26' as datetime)
    union all
      select cast('2011-05-26' as datetime)
    )
    SELECT DATENAME(month,d)+'-'+DATENAME(year,d)
    FROM testdata
    GROUP BY DATEPART(year,d), DATEPART(month,d), DATENAME(month,d),DATENAME(year,d)
    ORDER BY DATEPART(year,d), DATEPART(month,d)
    

    SELECT DATENAME(month,ReportDate)+'-'+DATENAME(year,ReportDate)
    FROM [EnvelopsDB].[dbo].[Envelopes]
    GROUP BY DATEPART(year,ReportDate), DATEPART(month,ReportDate), DATENAME(month,ReportDate),DATENAME(year,ReportDate)
    ORDER BY DATEPART(year,ReportDate), DATEPART(month,ReportDate)
    

    【讨论】:

    • 这没有给出我想要的结果。我期待这样的SELECT DISTINCT right(convert(varchar,ReportDate,106),8) FROM [EnvelopsDB].[dbo].[Envelopes] ORDER BY ReportDate desc
    • 您要按日期顺序订购吗?
    【解决方案2】:

    你可以像这样使用 GROUP BY 而不是 DISTINCT

    SELECT SUBSTRING (convert(varchar, ReportDate, 100),1,3) +'-'+
            SUBSTRING (convert(varchar, ReportDate, 100),8,4 ) 
    FROM [EnvelopsDB].[dbo].[Envelopes]
    GROUP BY SUBSTRING (convert(varchar, ReportDate, 100),1,3) +'-'+
              SUBSTRING (convert(varchar, ReportDate, 100),8,4 ) 
    

    使用 ReportDate desc 的 order by,使用 row_number() 而不是 group by。

    select substring(convert(varchar, Env.ReportDate, 100),1,3) +'-'+
              substring(convert(varchar, Env.ReportDate, 100),8,4 )
    from (select
            ReportDate,
            row_number() over(partition by datepart(year, ReportDate), datepart(month, ReportDate)
                              order by (select 1)) as rn
          from [EnvelopsDB].[dbo].[Envelopes]) as Env    
    where Env.rn = 1
    order by Env.ReportDate desc
    

    【讨论】:

    • 从这个 SQL 如何按降序对结果进行排序。
    【解决方案3】:

    我认为最近这里有一个类似的问题,我现在找不到,但答案是这样的:

    SELECT
      SUBSTRING(CONVERT(varchar, ReportDate, 100), 1, 3) + '-' +
      SUBSTRING(CONVERT(varchar, ReportDate, 100), 8, 4)
    FROM [EnvelopsDB].[dbo].[Envelopes]
    GROUP BY
      SUBSTRING(CONVERT(varchar, ReportDate, 100), 1, 3),
      SUBSTRING(CONVERT(varchar, ReportDate, 100), 8, 4)
    ORDER BY MIN(ReportDate)
    

    另外,虽然您选择以mmm-yyyy 格式显示输出的方式基本上没问题,但我可能会做同样的事情略有不同。这里:

    SELECT
      LEFT(DATENAME(month, ReportDate), 3) + '-' +
      DATENAME(year,  ReportDate)
    FROM [EnvelopsDB].[dbo].[Envelopes]
    GROUP BY
      DATENAME(month, ReportDate),
      DATENAME(year,  ReportDate)
    ORDER BY MIN(ReportDate)
    

    【讨论】:

      【解决方案4】:

      如果您不介意结果集中有一个额外的列,那么这将起作用。

      SELECT DISTINCT
          REPLACE(RIGHT(CONVERT(VARCHAR(11), ReportDate, 106), 8), ' ', '-') AS [Mon-YYYY],
          RANK() OVER(ORDER BY CONVERT(VARCHAR(7), ReportDate, 120) /* [YYYY-MM]*/ DESC) AS r_order
      FROM [EnvelopsDB].[dbo].[Envelopes]
      ORDER BY r_order DESC
      
      如果您不想为 MMM-YYYY 提供列别名(然后您可以在 ORDER BY 中使用),您不能只执行 **ORDER BY 1 DESC** 吗? 选择不同的 SUBSTRING (convert(varchar, ReportDate, 100),1,3) +'-'+ SUBSTRING (convert(varchar, ReportDate, 100),8,4 ) FROM [信封数据库].[dbo].[信封] 按 1 DESC 订购 或者只是添加一个列别名: 选择不同的 SUBSTRING (convert(varchar, ReportDate, 100),1,3) +'-'+ SUBSTRING (convert(varchar, ReportDate, 100),8,4 ) 作为 ReportDate FROM [信封数据库].[dbo].[信封] ORDER BY ReportDate DESC

      【讨论】:

      • 啊——我明白了。这在最初的问题中并不清楚。我现在重新阅读并看到了那部分。
      猜你喜欢
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 2015-02-26
      • 1970-01-01
      • 1970-01-01
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多