Lors de la boucle dans SQL Server 2008 itérer sur une date, puis INSÉREZ
J'ai une table avec un peu de colonnes, dont l'une est une colonne de type Timestamp. Mais à l'heure actuelle dans ce tableau n'est pas un enregistrement pour chaque jour. Sens, il y a des dossiers pour le 1er janvier et le 2 janvier, mais pas de dossiers avec 3 janvier ou le 4 janvier dans le champ d'Horodatage. Cependant, il existe des enregistrements continue pour le 5 janvier et le 6 janvier, et ainsi de suite. Fondamentalement, les week-ends et les autres aléatoire jours sont manquants.
Je suis en train d'écrire un script qui analyse cette table à partir de la date de début à la date de fin (quelle que soit la plage de dates-je choisir), et itérer sur cette date, et si un enregistrement n'existe pas avec les dates de cette date, insérer un nouvel enregistrement de la date dans le champ Timestamp, mais vide/NULL données pour le reste de la les champs.
Voici le pseudo-code que j'ai obtenu jusqu'à présent, et je pense que cette approche est la bonne:
DECLARE @StartDate AS DATETIME
DECLARE @EndDate AS DATETIME
DECLARE @CurrentDate AS DATETIME
SET @StartDate = '2015-01-01'
SET @EndDate = GETDATE()
SET @CurrentDate = @StartDate
WHILE (@CurrentDate < @EndDate)
BEGIN
SELECT * FROM myTable WHERE myTable.Timestamp = "@CurrentDate"
IF @@ROWCOUNT < 1
print @CurrentDate
/*insert a new row query here*/
SET @CurrentDate = convert(varchar(30), dateadd(day,1, @CurrentDate), 101); /*increment current date*/
END
Voici la SQLFiddle - http://sqlfiddle.com/#!6/06c73/1
Je suis en train d'écrire mon premier script dans SQL Server Management Studio 2008 et j'ai quelque chose que je pense que peut être pour un utilisateur intermédiaire. Je suis un PHP/MySQL développeur, et je suis très familier avec ces technologies, mais je suis nouvelle marque de SQL et VBScript. Je comprends les concepts de la programmation et de la logique, mais c'est bien autre chose que ce à quoi je suis habitué.
J'apprécie beaucoup tous de l'aide et la compréhension de l'avance!
OriginalL'auteur Armin | 2015-03-18
Vous devez vous connecter pour publier un commentaire.
SQL est un jeu basé sur la langue et boucles devrait être un dernier recours. De sorte que la mise en fonction de l'approche serait d'abord de générer toutes les dates qui vous conviennent et de les insérer en une seule fois, plutôt que de le bouclage et l'insertion d'un à la fois. Aaron Bertrand a écrit une grande série sur la génération d'un ensemble ou d'une séquence sans boucles:
La partie 3 est particulièrement pertinent car il traite avec les dates.
En supposant que vous n'avez pas de Calendrier de table, vous pouvez utiliser le bac de CTE méthode pour générer une liste de dates entre le début et dates de fin.
J'ai sauté quelques détails sur la façon dont cela fonctionne, qu'il est protégé par l'article lié, en substance, il commence avec une codés en dur tableau de 10 lignes, puis se joint à cette table avec elle-même pour obtenir 100 lignes (10 x 10), puis se joint à cette table de 100 lignes à elle-même pour obtenir 10 000 lignes (je me suis arrêté à ce point, mais si vous avez besoin de plus de lignes, vous pouvez ajouter d'autres jointures).
À chaque étape de la production est une seule colonne appelée
N
avec une valeur de 1 (pour garder les choses simples). Dans le même temps que la définition de la façon de générer 10 000 lignes, en fait, je dis SQL Server pour générer seulement le nombre requis par l'aide deTOP
et la différence entre le début et date de fin -TOP(DATEDIFF(DAY, @StartDate, @EndDate) + 1)
. Cela évite de travail inutile. J'ai dû ajouter 1 à la différence d'assurer à la fois les dates ont été inclus.À l'aide de la fonction de classement
ROW_NUMBER()
- je ajouter un nombre supplémentaire pour chacune des lignes générées, puis-je ajouter ce numéro incrémentiel à la date de votre départ pour obtenir la liste des dates. DepuisROW_NUMBER()
commence à 1, j'ai besoin de déduire 1 à partir de cela pour s'assurer que la date de départ est inclus.Alors il serait juste être un cas d'exclusion de dates qui existent déjà à l'aide de
NOT EXISTS
. J'ai joint les résultats de la requête ci-dessus dans leur propre CTE appelédates
:Exemple sur SQL Violon
Si vous deviez créer un calendrier de table (comme décrit dans les articles liés), alors il peut ne pas être nécessaire d'insérer ces lignes supplémentaires, vous pouvez simplement créer votre jeu de résultats à la volée, quelque chose comme:
ADDITIF
Pour répondre à votre question réelle de votre boucle serait écrit comme suit:
Exemple sur SQL Violon
Je ne préconise pas cette approche, tout simplement parce que quelque chose est fait une fois ne signifie pas que je ne devrait pas démontrer la bonne façon de faire.
DE PLUS AMPLES EXPLICATIONS
Depuis le empilés CTE méthode peut avoir plus compliqué de le définir en fonction de l'approche que je vais simplifier en utilisant les sans-papiers du système de tableau
master..spt_values
. Si vous exécutez:Vous verrez que vous obtenez tous les nombres de 0 -2047.
Maintenant, si vous exécutez:
Vous obtenez toutes les dates à partir de la date de votre départ à 2047 jours dans le futur. Si vous ajouter une clause where permet de le limiter à des dates avant votre date de fin:
Maintenant vous avez toutes les dates dont vous avez besoin dans un seul jeu basé sur une requête, vous pouvez éliminer les lignes qui existent déjà dans votre table à l'aide de
NOT EXISTS
Enfin, vous pouvez insérer ces dates dans votre table à l'aide de
INSERT
J'espère que cela va d'une certaine manière de montrer que le jeu de base est non seulement beaucoup plus efficace, il est plus simple aussi.
OriginalL'auteur GarethD