Нужна последняя запись дня, из диапазона дней - PullRequest
2 голосов
/ 21 июля 2010

Хорошо, вот в чем проблема, у меня есть 5 разных таблиц, созданных богом, кто знает, у кого разные данные, и мне нужно объединить их в одну таблицу.

Моя первая проблема заключается в том, что каждый день имеет метку времени, но мне нужно только добавлять последние записи каждый день, так как я могу каждый день искать последние записи и сохранять их в новой таблице, большинство из этих таблиц большие около 400 миллионов записей.

Следующий запрос возвращает мне последний регистр, но мне нужно искать каждый день, последний регистр (когда кто-то связывался с работой, и он делал это каждые 15 минут, каждый день получая много дублирующих данных).

Диапазон дней - с 1 января 2006 года по текущий день (в зависимости от таблицы), а некоторые - до 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 ]

2 голосов
/ 21 июля 2010

Вы не упомянули, какая версия 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
0 голосов
/ 21 июля 2010

Попробуйте:

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
0 голосов
/ 21 июля 2010

Мне нравится решение, опубликованное Томасом, и я согласен с ним, поскольку запрос без необходимости использовать курсор почти всегда предпочтительнее, чем запрос, использующий его. (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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...