2010-07-20 6 views
2

Ok heres le problème, j'ai 5 tables différentes créées par dieu sait qui chacune avec des données différentes, et je dois les fusionner dans une seule table. Mon premier problème est que chaque jour a un horodatage mais je n'ai besoin que des derniers enregistrements ajoutés chaque jour, alors comment puis-je chercher chaque jour les derniers enregistrements et les enregistrer sur une nouvelle table, la plupart de ces tables sont gros autour de 400 millions de disques. La requête suivante me renvoie le dernier registre, mais j'ai besoin de rechercher chaque jour, dernier registre (comme quelqu'un gâcher le travail et il le fait chaque 15 minutes pour chaque jour en faisant beaucoup de données en double).Besoin des derniers enregistrements d'un jour, à partir d'une gamme de jours

La gamme des jours est de 1 de janvier 2006 à jour en cours (selon le tableau) que certains vont jusqu'à 2008.

Jusqu'à présent, j'ai cela.

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

Cela me apporter un résultat comme

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  
+2

Pouvez-vous ajouter des noms de colonne à la sortie? – mrdenny

+0

Ouais désolé pour le manque de colonnes, j'ai coupé car il a plus de 50 colonnes. – Enrique

+0

ne pas utiliser le curseur sauf s'il n'y a pas d'autre moyen - il n'y a pas d'autre moyen? –

Répondre

0

Essayez ceci:

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 

L'idée ici est de créer une sous-requête des dates maximales groupées par jour puis rejoindre sur la table principale.

Si vous souhaitez identifier les valeurs qui se situent en dehors de cette plage afin de les supprimer, vous pouvez faire une jointure externe gauche contre l'ensemble:

/** 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 

Cette instruction SELECT utilise des valeurs de mois et l'année dans la sous-requête afin de faire une approche de traitement par lots et de sélectionner/supprimer des enregistrements en plus petites quantités.

La réponse originale est ci-dessous:

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

Une question rapide ici, au cas où je ne veux pas tout traiter en 1 fois, comment puis-je définir des intervalles comme 1 semaine ou 1 mois? ou un nombre ou des registres. – Enrique

+0

Oui, cela peut être fait avec de nouvelles colonnes dans la sous-requête. Edits ci-dessus. – 8kb

+0

Une dernière question, au cas où je voudrais supprimer celles qui ne correspondent pas au résultat de la recherche? J'ai une erreur dans la comparaison – Enrique

2

Vous n'avez pas mentionné quelle version de SQL Server (ni beaucoup de détails sur la façon dont vous êtes actuellement faites), mais si elle est SQL Server 2005+ vous:

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

Je suis un peu perdu avec la réponse Thomas, au moment où je veux simplement supprimer les mauvaises données sur la base de données plus tard, je les fusionner, pour ce que je crois « AVEC DATA » Je crée une unision sans besoin d'avoir recours aux jointures. – Enrique

+0

@Enrique - J'utilise une expression de table commune. J'ai nommé mon CTE "Data". J'ai révisé mon message pour fournir un meilleur nom pour le CTE (dans ce cas "NumberedData"). En bref, j'ai le numéro de système à chaque ligne, de sorte qu'il recommence à numéroter chaque jour et que la dernière heure ait le nombre le plus bas (c'est-à-dire 1 pour la dernière heure, 2 pour la prochaine plus récente etc.). – Thomas

0

J'aime la solution Thomas affichée et irait avec que depuis une requête sans avoir à utiliser un curseur est à peu près toujours préférable à celui qui utilise un. (SQL est construit pour la logique SET donc il sera toujours plus efficace de faire ce qu'il fait de mieux.)

Vous avez également dit que vous deviez obtenir plusieurs lignes par jour tant qu'elles étaient toutes stockées en même temps . L'expression CTE telle qu'elle est écrite dans la solution Thomas ne vous donne que la dernière seule qui puisse suffire. Sinon, vous pourriez facilement modifier sa solution. Ci-dessous est une solution de curseur puisque vous avez eu de la curiosité à leur sujet. Je lui donne le conseil de ne pas l'utiliser mais sache que c'est possible.

Vous utiliseriez, bien sûr, une table réelle plutôt qu'une variable de table comme ci-dessous si vous souhaitiez conserver les résultats pour une analyse ultérieure.

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