【问题标题】:create an classification for months ordered为订购的月份创建分类
【发布时间】:2017-08-09 14:32:46
【问题描述】:

我正在尝试在我的查询中创建一个列以显示相对于日期的有序分类(显示 1、2、3(如第一、第二、第三...))...在我当前的查询中过滤了过去 12 个月的数据(例如,从 2016 年 1 月 9 日到 2017 年 8 月 31 日)

使用DATEADD(mm; DATEDIFF(m; - 1; GETDATE()) - 12; 0)

第一次约会和

DATEADD(s; - 1; DATEADD(mm; DATEDIFF(m; 0; GETDATE()) + 1; 0))

当月的最后一天。而且我还有两列,一列是月份,另一列是年份,它们都是从数据中存在的文档日期列中提取的(我正在使用

MONTH(dbo.Mov_Venda_Cab.dtmData)YEAR(dbo.Mov_Venda_Cab.dtmData))

我的目标是有一个列显示这样的内容:

如果月份是间隔中的第一个(如果是第 9 个月和 2016 年)必须显示 1,如果是第二个(第 10 个月和 2016 年),则显示 2,一直持续到当前月份(即是 8 和 2017 年)并显示 12。

如果静态的值我可以做一个简单的案例并实现我想要的。我的问题是,当我获得按当前日期和 12 个月后过滤的数据时,我无法获得相同的结果,因为我不知道在 CASE 表达式中应该做什么。

所以它可以帮助我的专栏是:

Item ; Qty ; Month ; Year ; dtmData ; orderedMonth

原始查询:

SELECT DISTINCT DATEADD(mm, DATEDIFF(m, - 1, GETDATE()) - 12, 0)                            AS DATA_INI,
  DATEADD(s,                            - 1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()) + 1, 0)) AS DATA_FIM,
  dbo.Mov_Venda_Lin.Id,
  MONTH(dbo.Mov_Venda_Cab.dtmData)                                      AS Mes,
  YEAR(dbo.Mov_Venda_Cab.dtmData)                                       AS Ano,
  dbo.Mov_Venda_Lin.fltValorMercadoriaSIVA * dbo.Mov_Venda_Cab.intSinal AS Mercadoria,
  dbo.Mov_Venda_Lin.fltValorLiquido        * dbo.Mov_Venda_Cab.intSinal AS ValorLiquido,
  CASE
    WHEN tbl_tipos_documentos.bitconsideraqtdmapas = 1
    THEN (Mov_Venda_Lin.fltQuantidade * mov_venda_cab.intsinal)
    ELSE 0
  END                                      AS Quantidade,
  dbo.Mov_Venda_Lin.strCodSeccao           AS Seccao,
  dbo.Mov_Venda_Lin.strAbrevTpDoc          AS TpDoc,
  dbo.Tbl_Tipos_Documentos.strDescricao    AS DescTpDoc,
  dbo.Mov_Venda_Lin.intNumLinha            AS Linha,
  dbo.Mov_Venda_Lin.strCodExercicio        AS Exercicio,
  dbo.Mov_Venda_Cab.strAbrevMoeda          AS Moeda,
  dbo.Mov_Venda_Cab.fltCambio              AS Cambio,
  dbo.Mov_Venda_Lin.strCodArtigo           AS Artigo,
  dbo.Tbl_Gce_Artigos.strDescricao         AS DescArtigo,
  dbo.Mov_Venda_Lin.strCodClassMovStk      AS MovStk,
  dbo.Tbl_ClassificacaoMovStk.strDescricao AS DescMovStk,
  CASE
    WHEN mov_venda_cab.inttpentidade = 0
    THEN tbl_gce_tipos_entidade.strcodigo
    ELSE NULL
  END AS TpEntidade,
  CASE
    WHEN mov_venda_cab.inttpentidade = 0
    THEN tbl_gce_tipos_entidade.strdescricao
    ELSE NULL
  END AS DescTpEntidade,
  CASE
    WHEN mov_venda_cab.intcodentidade <> 0
    THEN mov_venda_cab.intcodentidade
    ELSE NULL
  END AS CodEntidade,
  CASE
    WHEN mov_venda_cab.inttpentidade  = 0
    AND mov_venda_cab.intcodentidade <> 0
    THEN 'Cliente'
    WHEN mov_venda_cab.inttpentidade  = 1
    AND mov_venda_cab.intcodentidade <> 0
    THEN 'Outro Devedor'
    ELSE NULL
  END AS TipoEntidade,
  CASE
    WHEN mov_venda_cab.inttpentidade = 0
    THEN tbl_clientes.strnome
    ELSE tbl_outros_devedores.strnome
  END                                    AS DescNome,
  dbo.Tbl_SubZonas.strAbrevZona          AS Zona,
  dbo.Tbl_Zonas.strDescricao             AS DescZona,
  dbo.Mov_Venda_Cab.strAbrevSubZona      AS SubZona,
  dbo.Tbl_SubZonas.strDescricao          AS DescSubZona,
  dbo.Mov_Venda_Cab.intCodVendedor       AS Vendedor,
  dbo.Tbl_Gce_Vendedores.strNome         AS DescNomeVend,
  dbo.Tbl_Gce_Artigos.strCodCategoria    AS Categoria,
  dbo.Tbl_Gce_Categorias.strDescricao    AS DescCategoria,
  dbo.Tbl_Gce_Artigos.strTpArtigo        AS TpArtigo,
  dbo.Tbl_Gce_Tipos_Artigos.strDescricao AS DescTpArtigo,
  CAST(NULL AS VARCHAR(13))              AS CodFamiliaAgrup,
  CAST(NULL AS VARCHAR(35))              AS DescFamAgrup,
  CAST(NULL AS VARCHAR(13))              AS CodFamiliaRes,
  CAST(NULL AS VARCHAR(35))              AS DescFamRes,
  dbo.Mov_Venda_Cab.strForteAbrevMoeda   AS abrevmoeda,
  dbo.Mov_Venda_Cab.fltForteCambio       AS fortecambio
FROM dbo.Mov_Venda_Lin WITH (NOLOCK)
LEFT OUTER JOIN dbo.Mov_Venda_Cab WITH (NOLOCK)
  ON dbo.Mov_Venda_Lin.strCodSeccao     = dbo.Mov_Venda_Cab.strCodSeccao
  AND dbo.Mov_Venda_Lin.strAbrevTpDoc   = dbo.Mov_Venda_Cab.strAbrevTpDoc
  AND dbo.Mov_Venda_Lin.strCodExercicio = dbo.Mov_Venda_Cab.strCodExercicio
  AND dbo.Mov_Venda_Lin.intNumero       = dbo.Mov_Venda_Cab.intNumero
LEFT OUTER JOIN dbo.Tbl_Gce_Armazens WITH (NOLOCK)
  ON dbo.Mov_Venda_Lin.strCodArmazem = dbo.Tbl_Gce_Armazens.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Artigos WITH (NOLOCK)
  ON dbo.Tbl_Gce_Artigos.strCodigo = dbo.Mov_Venda_Lin.strCodArtigo
LEFT OUTER JOIN dbo.Tbl_Gce_ArtigosFamilias WITH (NOLOCK)
  ON dbo.Tbl_Gce_Artigos.strCodigo = dbo.Tbl_Gce_ArtigosFamilias.strCodArtigo
LEFT OUTER JOIN dbo.Tbl_Gce_Familias WITH (NOLOCK)
  ON dbo.Tbl_Gce_ArtigosFamilias.strCodFamilia = dbo.Tbl_Gce_Familias.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_ArtigosReferencias WITH (NOLOCK)
  ON dbo.Tbl_Gce_Artigos.strCodigo = dbo.Tbl_Gce_ArtigosReferencias.strCodArtigo
LEFT OUTER JOIN dbo.Tbl_Gce_Referencias WITH (NOLOCK)
  ON dbo.Tbl_Gce_ArtigosReferencias.strCodReferencia = dbo.Tbl_Gce_Referencias.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Tipos_Artigos WITH (NOLOCK)
  ON dbo.Tbl_Gce_Artigos.strTpArtigo = dbo.Tbl_Gce_Tipos_Artigos.strCodigo
LEFT OUTER JOIN dbo.Tbl_Clientes WITH (NOLOCK)
  ON dbo.Mov_Venda_Cab.intCodEntidade = dbo.Tbl_Clientes.intCodigo
LEFT OUTER JOIN dbo.Tbl_Direccoes WITH (NOLOCK)
  ON dbo.Mov_Venda_Cab.intCodEntidade = dbo.Tbl_Direccoes.intCodigo
  AND dbo.Mov_Venda_Cab.intDireccao   = dbo.Tbl_Direccoes.intNumero
  AND dbo.Mov_Venda_Cab.intTpEntidade = dbo.Tbl_Direccoes.intTp_Entidade
LEFT OUTER JOIN dbo.Tbl_Outros_Devedores WITH (NOLOCK)
  ON dbo.Mov_Venda_Cab.intCodEntidade = dbo.Tbl_Outros_Devedores.intCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Vendedores WITH (NOLOCK)
  ON dbo.Mov_Venda_Cab.intCodVendedor = dbo.Tbl_Gce_Vendedores.intCodigo
LEFT OUTER JOIN dbo.Tbl_Tipos_Documentos WITH (NOLOCK)
  ON dbo.Mov_Venda_Cab.strAbrevTpDoc = dbo.Tbl_Tipos_Documentos.strAbreviatura
LEFT OUTER JOIN dbo.Tbl_SubZonas WITH (NOLOCK)
  ON dbo.Mov_Venda_Cab.strAbrevSubZona = dbo.Tbl_SubZonas.strAbreviatura
LEFT OUTER JOIN dbo.Tbl_Zonas WITH (NOLOCK)
  ON dbo.Tbl_SubZonas.strAbrevZona = dbo.Tbl_Zonas.strAbreviatura
LEFT OUTER JOIN dbo.Tbl_Gce_Categorias WITH (NOLOCK)
  ON dbo.Tbl_Gce_Artigos.strCodCategoria = dbo.Tbl_Gce_Categorias.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Seccoes WITH (NOLOCK)
  ON dbo.Mov_Venda_Cab.strCodSeccao = dbo.Tbl_Gce_Seccoes.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Tipos_Entidade WITH (NOLOCK)
  ON dbo.Tbl_Clientes.strTpEntidade = dbo.Tbl_Gce_Tipos_Entidade.strCodigo
LEFT OUTER JOIN dbo.Tbl_ClassificacaoMovStk WITH (NOLOCK)
  ON dbo.Mov_Venda_Lin.strCodClassMovStk = dbo.Tbl_ClassificacaoMovStk.strCodigo
WHERE (dbo.Mov_Venda_Cab.intTpEntidade = 0
  OR dbo.Mov_Venda_Cab.intTpEntidade    IS NULL)
  AND (dbo.Mov_Venda_Cab.strAbrevTpDoc                            IN ('CRFCX', 'FACIV', 'FACTC', 'FCTA', 'LANIV', 'LOFX', 'LONC', 'LXANI', 'NCFCX', 'NFACC', 'NFACE', 'NFACM', 'NFACT', 'NNCRC', 'NNCRE', 'NNCRM', 'NNDEB', 'NNDEC', 'NNDEV', 'NVDIC', 'NVDIN', 'XLACC', 'XLACD'))
  AND (dbo.Mov_Venda_Cab.strCodSeccao                             IN ('1', 'ENCT1', 'ENCT2', 'ENCT3', 'ENCT4', 'ENCT5', 'ENCT6'))
  AND (dbo.Mov_Venda_Cab.dtmData         > DATEADD(mm, DATEDIFF(m, - 1, GETDATE()) - 12, 0))
  AND (dbo.Mov_Venda_Cab.dtmData        <= DATEADD(s,              - 1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()) + 1, 0)))
  AND (dbo.Mov_Venda_Lin.intTpLinha      > 2)
  AND (dbo.Mov_Venda_Cab.bitAnulado      = 0)
  AND (dbo.Mov_Venda_Cab.bitConvertido   = 0) 

【问题讨论】:

  • 您使用的是什么数据库服务器?请列出您当前的查询
  • Sql Server 2012...原始查询很长,无法在此处发布...
  • 添加了原始查询(抱歉,它有点长......这就是我简化它的原因......

标签: sql sql-server date


【解决方案1】:

幸运的是,有一种方法比使用一堆 CASE 语句要简单得多。您可以使用ROW_NUMBER 函数。

首先,不要将日期分成月份和年份。只需使用Getdate() 来计算您想要的范围并将您的源日期与该范围进行比较。然后添加ROW_NUMBER 以获得您的排序输出:

SELECT 
    *
    ,ordered_output = (ROW_NUMBER()OVER(PARTITION BY grouping_field ORDER BY cast(dtmData as datetime) ASC))
FROM Mov_Venda_Cab
WHERE cast(dtmData as datetime) >= getdate() - 365

此示例假设您有一些 ID 字段或类似的字段,您希望在这些字段上对您的输出进行分组,在示例中由 grouping_field 表示。您的结果将如下所示:

grouping_field  dtmData    ordered_output 
1               8/1/2017     1
1               8/2/2017     2
1               8/3/2017     3
2               8/1/2017     1
2               8/2/2017     2
2               8/3/2017     3

如果您不想对输出进行分组,只需按日期对所有内容进行排序,则可以省略 PARTITION BY grouping_field 文本。你会得到类似的东西:

dtmData    ordered_output 
8/1/2017     1
8/2/2017     2
8/3/2017     3
8/4/2017     4
8/5/2017     5
8/6/2017     6

编辑:Asker 澄清说,同一月份的所有记录都应该得到相同的有序输出。

为此,您首先需要为每个月/年组合分配一个排名,然后使用两层子查询将其重新加入主表:

SELECT b.*, c.month_rank
from Mov_Venda_Cab as b
inner join
    (select mnt, yr, ROW_NUMBER() OVER(ORDER BY A.yr, A.mnt) AS month_rank
    from (
        SELECT DISTINCT
            MONTH(dtmData) as mnt
            , YEAR(dtmData) as yr
        from Mov_Venda_Cab
        WHERE cast(dtmData as datetime) >= getdate() - 365
        ) as a
    ) as c
on MONTH(b.dtmData) = c.mnt and YEAR(b.dtmData) = c.yr

【讨论】:

  • 几乎工作......有序输出应该按月完成,所以如果我使用分区(ROW_NUMBER() OVER(PARTITION BY mov_venda_cab.dtmdata ORDER BY mov_venda_cab.dtmdata ASC) 作为分类)我得到所有行都编号为 1 ...如果我丢弃 PARTITION 我得到所有编号为 asn 1,2,3,4,.....128999 等的行...因为是按行而不是按月/年分组.
  • 我不确定我是否完全理解您的问题,但如果您想按月分组,您可以将月份从dtmData 中拉出并按此划分
  • 我做到了……几乎得到了我想要的。得到了我想要的所有行是这样的:
  • 听起来你只需要摆弄它来解释你的问题中不明显的数据细节:-)
  • 我做到了……几乎得到了我想要的。我想要的是这个:[code] Item |数量 | dtm数据 |月 |年份 | ORDERED_OUTPUT 01.001 | 12 | 2016 年 10 月 9 日 | 9 | 2016 | 1 01.002 | 5 | 22/09/2016 | 9 | 2016 | 1 01.001| 3| 16/10/2016| 10 | 2016 | 2 01.001| 7 | 2016 年 1 月 11 日| 11 | 2016 | 3 01.002| 10 | 14/11/2016| 11 | 2016 | 3 02.004| 2 | 2016 年 11 月 22 日 | 11 | 2016 | 3 01.001| 10 | 2016 年 18 月 12 日 | 12 | 2016 | 4 01.002| 8 | 2017 年 10 月 1 日 | 1 | 2017 | 5[代码] 基本上,无论我一个月有多少行,所有行都应该获得相同的“排名”。希望我能澄清一点......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-04
  • 2023-01-23
  • 2021-02-15
  • 1970-01-01
相关资源
最近更新 更多