为订购的月份创建分类

时间:2017-08-09 14:32:46

标签: sql sql-server date

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

ORIGINAL QUERY:

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) 

1 个答案:

答案 0 :(得分: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