从一系列日子开始,需要一天的最后记录

时间:2010-07-20 22:16:35

标签: sql-server datetime cursor

好的,这是问题,我有5个不同的表由上帝知道谁知道每个人有不同的数据,dI需要将它们合并在一个表中。

我的第一个问题是每天都有时间戳但我只需要每天添加最后一条记录,那么如何每天搜索最后的记录并将它们保存在新表中,这些表大部分都很大大约4亿条记录。

以下查询返回最后一个注册表,但我需要搜索每一天,最后一个注册表(因为有人搞乱了这个工作,并且每天15分钟就做了很多重复数据)。

日期范围从2006年1月1日到当天(取决于表格),有些日子一直持续到2008年。

到目前为止,我有这个。

SELECT * FROM [PDP].[dbo].[Existencia_WH_PRISM_BACKUP]
        WHERE dExD_Fecha = (SELECT MAX(dExD_Fecha)
        FROM dbo.Existencia_WH_PRISM_BACKUP)

这给我带来了像

这样的结果
NombreEntidad   dExD_Fecha  LDWHSE  LDLOCN  LDRESC  LDLOTN  LDGRDE  LDLOCQ  LDUMSR  LDRSCL  LDRSSC  LDQRUM  LDRCUM  LDPOTF  LDREVL  LDCLCD  LDOOIN  LDAVPL  LDOHIN  LDDVIN  LDDWIP  LDQYRM  LDQYRS  LDDLRC  LDTLRC  LDTRAN  LDFIFO  LDETD   LDETT   LDEXPD  LDVNNO  LDPOSQ  LDDTMT  LDACTP  LDZONE  LDAVPT  LDRTND  LDCDDT  LDLSQY  LDAGE1  LDAGE2  LDAGE3  LDAGE4  LDAGE5  LDAMIR  LDRCLS  LDPTAW  LDCSPK  LDQYOU  LDBLNK
HDZALM  2010-05-28 12:01:00.000 1T  A04 405120  K0146       864.000000  CJ  PT  40  864.000000  CJ  0.000000        STOC    N   2   Y   Y   N   0.000000    0.000000    1100527 75934   6659304 1100527 1100527 61504   1110527     5   1100527 N   A   Y           0.000000    9999999 9999999 9999999 9999999 9999999 N   Y   Y   N   0.000000    
HDZALM  2010-05-28 12:01:00.000 1T  A04 405120  K0147       1944.000000 CJ  PT  40  1944.000000 CJ  0.000000        STOC    N   2   Y   Y   N   0.000000    0.000000    1100527 120112  6665777 1100527 1100527 120051  1110527     5   1100527 N   A   Y           0.000000    9999999 9999999 9999999 9999999 9999999 N   Y   Y   N   0.000000    
HDZALM  2010-05-28 12:01:00.000 1T  A05 405120  K0146       2052.000000 CJ  PT  40  2052.000000 CJ  0.000000        STOC    N   2   Y   Y   N   0.000000    0.000000    1100527 54402   6658261 1100527 1100527 54146   1110527     5   1100527 N   A   Y           0.000000    9999999 9999999 9999999 9999999 9999999 N   Y   Y   N   0.000000    
HDZALM  2010-05-28 12:01:00.000 1T  A05 405120  K0147       2160.000000 CJ  PT  40  2160.000000 CJ  0.000000        STOC    N   2   Y   Y   N   0.000000    0.000000    1100527 153911  6671885 1100527 1100527 153714  1110527     5   1100527 N   A   Y           0.000000    9999999 9999999 9999999 9999999 9999999 N   Y   Y   N   0.000000    
HDZALM  2010-05-28 12:01:00.000 1T  A06 405120  K0146       4212.000000 CJ  PT  40  4212.000000 CJ  0.000000        STOC    N   2   Y   Y   N   0.000000    0.000000    1100527 43743   6657177 1100527 1100527 43625   1110527     5   1100526 N   A   Y           0.000000    9999999 9999999 9999999 9999999 9999999 N   Y   Y   N   0.000000    

3 个答案:

答案 0 :(得分:2)

您没有提到SQL Server的版本(也没有关于您当前如何执行此操作的详细信息),但是如果它是SQL Server 2005+,您可以:

With NumberedData As
    (
    Select ...
        , Row_Number() Over ( Partition By DateDiff(d, 0, E.dExD_Fetcha) 
                              Order By E.dExD_Fetcha Desc ) As Num
    From PDFP.dbo.[Existencia_WH_PRISM_BACKUP] As E
    )
Select ...
From Data
Where Num = 1

答案 1 :(得分:0)

我喜欢Thomas发布的解决方案,因为无需使用游标的查询几乎总是优于使用游标的查询。 (SQL是为SET逻辑构建的,所以它总能更有效地做它最擅长的事情。)

您还说过,只要它们全部存储在同一时间,您就需要每天获得多行。托马斯解决方案中写的CTE表达式只为您提供了最后一个表达式。否则你可以轻松修改他的解决方案。

下面是一个游标解决方案,因为你对它们有好奇心。我提供的建议是你不应该使用它,但你应该知道它是可能的。

如果您想保留结果以供以后分析,您当然会使用真实表而不是表变量。

DECLARE @t1 TABLE ( DtTm datetime )

DECLARE @Dt datetime        
DECLARE c CURSOR FOR 
    SELECT CONVERT(datetime, CONVERT(char(11), dExD_Fecha, 113))
    FROM [PDP].[dbo].[Existencia_WH_PRISM_BACKUP]
    GROUP BY CONVERT(char(11), dExD_Fecha, 113)

OPEN c
FETCH NEXT FROM c INTO @Dt
WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT INTO @t1 
    SELECT dExD_Fecha -- add any other fields you care to capture here and above to the table definition
    FROM [PDP].[dbo].[Existencia_WH_PRISM_BACKUP]
    WHERE dExD_Fecha = (
        SELECT MAX(dExD_Fecha)
        FROM [PDP].[dbo].[Existencia_WH_PRISM_BACKUP]
        WHERE CONVERT(datetime,CONVERT(char(11), dExD_Fecha, 113)) = @Dt)
    FETCH NEXT FROM c INTO @Dt
END

CLOSE c
DEALLOCATE c

SELECT * FROM @t1

答案 2 :(得分:0)

试试这个:

SELECT e.*
FROM [PDP].[dbo].[Existencia_WH_PRISM_BACKUP] e
INNER JOIN (
  SELECT MAX(dExd_Fecha) AS dExd_Fecha_Max
  FROM [PDP].[dbo].[Existencia_WH_PRISM_BACKUP]
  GROUP BY DATEADD(DD, DATEDIFF(DD, 0, dExd_Fecha), 0) 
) m
  ON e.dExD_Fecha = m.dExd_Fecha_Max
ORDER BY e.dEXd_Fecha

这里的想法是创建一个按日分组的最大日期的子查询,然后加入主表。

如果要识别超出该范围的值以便删除它们,可以对该集合执行左外连接:

/** DELETE FROM x **/
SELECT * 
FROM (
  SELECT 
    dExd_Fecha,
    YEAR(dExd_Fecha) AS dExd_Ano, 
    MONTH(dExd_Fecha) AS dExd_Semana, 
    NTILE(10) OVER (ORDER BY dExd_Fecha) AS dExd_Groupo  
  FROM [Existencia_WH_PRISM_BACKUP]
) x 
LEFT OUTER JOIN ( 
  SELECT MAX(dExd_Fecha) AS dExd_Fecha_Max 
  FROM [PDP].[dbo].[Existencia_WH_PRISM_BACKUP]  
  GROUP BY DATEADD(DD, DATEDIFF(DD, 0, dExd_Fecha), 0)   
) y 
ON x.dExd_Fecha = y.dExd_Fecha_Max
WHERE 
  x.dExd_Ano = 2010
  AND x.dExd_Semana = 1
  AND y.dExd_Fecha_Max IS NULL
ORDER BY x.dExd_Fecha

此SELECT语句使用子查询中的YEAR和MONTH值来执行批处理方法并以较小的数量选择/删除记录。

原始答案如下:

SELECT e.* 
FROM [PDP].[dbo].[Existencia_WH_PRISM_BACKUP] e 
INNER JOIN ( 
  SELECT 
    MAX(dExd_Fecha) AS dExd_Fecha_Max,

    /** get the year of the last date **/
    YEAR(MAX(DATEADD(YY, DATEDIFF(YY, 0, dExd_Fecha), 0))) AS dExd_Ano_Max,

    /** get the month of the last date **/
    MONTH(MAX(DATEADD(MM, DATEDIFF(MM, 0, dExd_Fecha), 0))) AS dExd_Mes_Max,

    /** get the week of the last date **/
    DATEPART(WEEK, MAX(dExd_Fecha)) AS dExd_Semana_Max,

    /** set a number to divide the total rows into ten groups **/
    NTILE(10) OVER (ORDER BY MAX(dExd_Fecha)) AS dExd_Groupo 

  FROM [PDP].[dbo].[Existencia_WH_PRISM_BACKUP] 
  GROUP BY DATEADD(DD, DATEDIFF(DD, 0, dExd_Fecha), 0)  
) m 
  ON e.dExD_Fecha = m.dExd_Fecha_Max 
WHERE 
  m.dExd_Ano_Max = 2010
  AND m.dExd_Mes_Max = 1