2
votes

SSIS - combiner les résultats uniquement si la clé n'existe pas dans le premier ensemble de données

J'essaie de combiner deux sources d'inventaire avec SSIS. Le premier contient des informations d'inventaire de notre nouveau système tandis que le second contient des données héritées. J'obtiens très bien les données des sources.

Les deux ensembles de données ont les mêmes colonnes, mais je souhaite uniquement obtenir les résultats du deuxième ensemble de données si la valeur ItemCode de cet enregistrement n'existe pas dans le premier ensemble de données.

Quelle transformation aurais-je besoin d'utiliser pour y parvenir?

Modifier - voici ce que j'ai jusqu'à présent dans mon flux de données.

 entrez la description de l'image ici

Je dois ajouter une transformation à la source Extract Legacy Item Data afin qu'elle supprime les enregistrements dont les codes article existent déjà dans la source Extract New Item Data .

/ p>

Les deux sources sont sur des serveurs différents donc je ne peux pas résoudre en modifiant la requête. Je voudrais également éviter d'exécuter la même requête que celle exécutée dans la source Extraire les nouvelles données d'élément .


5 commentaires

Avez-vous déjà combiné les sources de données dans le flux de données? Sinon, existe-t-il une clé unique (ou une combinaison de clés uniques) que chaque ensemble de données partage?


Je ne les ai pas encore combinés - oui, le code de l'article sera unique dans chaque ensemble de données, mais il peut être présent dans les deux. Je souhaite inclure uniquement les enregistrements du deuxième ensemble de données si le code d'élément n'existe pas dans le premier ensemble de données.


@ryansin alors vous avez la réponse dont vous avez besoin. l'utilisation de Lookups est plus rapide que l'utilisation de la transformation Merge Join, si les deux sources sont sur le même SQL Server que vous pouvez utiliser une commande SQL comme source


@ryansin quelque chose de nouveau?


Je n'ai pas eu l'occasion de vérifier cela ces derniers jours


3 Réponses :


0
votes

Tout d'abord, concernant le fait que vous utilisez SQL Server Destination, je vous suggère de lire la réponse suivante du gourou SSIS @billinkc:


Je vais fournir différentes méthodes pour y parvenir:

(1) Utilisation de la transformation de recherche

  1. Vous devez ajouter une tâche de flux de données, dans laquelle vous ajoutez le deuxième inventaire (ancien) comme source
  2. Ajoutez une transformation de recherche dans laquelle vous sélectionnez la première source d'inventaire comme table de recherche.
  3. Mappez la source et la table de recherche avec la colonne ItemCode
  4. Dans la transformation de recherche, sélectionnez Rediriger les lignes vers une sortie sans correspondance dans la liste déroulante.
  5. Utilisez la sortie Lookup no match pour obtenir les lignes souhaitées (non trouvées dans la première source d'inventaire)

Vous pouvez vous référer au lien ci-dessous, il contient des didacticiels étape par étape.

Lien utile

Anciennes versions de SSIS

Si vous utilisez d'anciennes versions de SSIS, vous ne trouverez pas la liste déroulante Rediriger les lignes vers une sortie sans correspondance . Au lieu de cela, vous devriez aller à la sortie Erreur de recherche, sélectionnez l'option Rediriger la ligne pour la situation Aucune correspondance , et utilisez la sortie d'erreur pour obtenir les lignes souhaitées.


(2) Utilisation de serveurs liés

Sur le deuxième inventaire, créez un serveur lié pour pouvoir connecter le premier serveur. Vous pouvez maintenant utiliser une commande SQL qui ne sélectionne que les lignes non trouvées dans la première source:

SELECT * FROM (
       SELECT *, ROW_NUMBER() OVER(PARTITION BY ItemCode ORDER BY SourceID) rn
       FROM StagingTable ) s
Where s.rn = 1

(3) Table de préparation + MERGE, MERGE JOIN , Transformation UNION ALL

Sur chaque commande SQL source, ajoutez une colonne de valeur fixe qui contient l'id source (1,2), exemple:

SELECT *, 1 as SourceID FROM Inventory

Vous peut combiner les deux sources dans une destination en utilisant l'une des transformations répertoriées ci-dessus, puis ajouter une deuxième tâche de flux de données pour importer des données distinctes de la table de préparation vers la destination en fonction de la colonne ItemCode, exemple:

SELECT *
FROM Inverntory2
WHERE NOT EXISTS (SELECT 1 FROM <Linked Server>.<database>.<schema>.Inverntory1 Inv1 WHERE Inverntory2.ItemCode = Inv1.ItemCode)

Remarque: vérifiez la réponse fournie par @ userfl89, elle contient des informations très détaillées sur l'utilisation de la transformation Merge Join et décrit une autre approche qui peut aider. Vous devez maintenant tester quelle approche correspond à vos besoins. Bonne chance


10 commentaires

Comment ajouter ma première source comme table de recherche? Dois-je simplement ressaisir la requête SQL que j'utilise pour obtenir le premier ensemble de données?


Oui, utilisez la même requête


Existe-t-il un moyen de le faire sans avoir à exécuter à nouveau la même requête? Je préfère interroger l'ensemble de données une seule fois si cela est possible


Je pense que vous avez mal compris ce que j'ai fourni. Vous ne devez avoir qu'une seule source oledb qui est le deuxième inventaire. Et une transformation de recherche qui est le premier inventaire. Vous n'êtes pas obligé d'écrire la requête deux fois


Oui, je peux réutiliser la source, mais je ne vois pas de moyen de rechercher le premier ensemble de données sans exécuter la même requête que celle utilisée pour extraire le premier ensemble de données. À moins que je ne manque quelque chose, j'aurais besoin de ré-interroger les mêmes données pour y parvenir?


Ah ok. Pourquoi ne pas utiliser une table intermédiaire puis extraire des données distinctes vers la destination


Vous pouvez utiliser la jointure par fusion, mais cela n'est pas recommandé du point de vue des performances


@ryansin ce soir, je vais fournir une réponse détaillée avec toutes les solutions possibles car j'écris depuis mon téléphone en ce moment.


Je vous remercie. J'ai également modifié ma question pour fournir plus d'informations.


@ryansin quelque chose de nouveau?



0
votes

Si les deux types de sources sont des bases de données SQL et qu'ils sont stockés sur le même serveur, vous pouvez utiliser une commande SQL comme source pour y parvenir:

SELECT *
FROM Inverntory2
WHERE NOT EXISTS (SELECT 1 FROM Inverntory1 WHERE Inverntory2.ItemCode = Inverntory1.ItemCode)

OU

SELECT Inverntory2.*
FROM Inverntory2 LEFT JOIN Inverntory1
     On Inverntory2.ItemCode = Inverntory1.ItemCode
WHERE Inverntory1.ItemCode IS NULL


1 commentaires

Malheureusement, ils sont sur des serveurs différents, j'ai donc besoin d'un moyen d'éliminer les résultats de la deuxième source après qu'il a été interrogé en fonction du fait que le code d'article existe déjà dans la première source



0
votes

Un exemple de ceci est ci-dessous. L'utilisation d'une destination SQL Server fonctionnera correctement, mais cela ne permet que le chargement vers une instance SQL Server locale, ce que vous voudrez peut-être envisager à l'avenir. Bien qu'une recherche fonctionne généralement mieux, la fusion des jointures peut être bénéfique dans certaines circonstances, par exemple lorsque de nombreuses colonnes supplémentaires sont introduites dans le flux de données, comme cela peut être fait avec vos ensembles de données. Il semble que @Hadi a expliqué comment faire cela avec une recherche, vous pouvez donc tester les deux approches dans un environnement hors production qui imite prod, puis évaluer les résultats pour déterminer la meilleure option.

  • Commencez par créer une table intermédiaire qui est un clone exact de l'une des tables. Les deux tables fonctionneront puisqu'elles ont la même définition. Assurez-vous que toutes les colonnes de la préparation autorisent les valeurs nulles.
  • Ajoutez une tâche d'exécution SQL pour effacer la table intermédiaire avant la tâche de flux de données en tronquant ou en supprimant, puis en créant la table.
  • Puisque ItemCode est un tri unique sur cette colonne dans chaque source OLE DB. Si vous ne modifiez pas déjà la commande Mode d'accès aux données en SQL dans les deux sources OLE DB et ajoutez une clause ORDER BY pour ItemCode . Pour ce faire, cliquez avec le bouton droit sur la source OLE DB et accédez à Afficher l'éditeur avancé > Propriétés d'entrée et de sortie > Sortie de la source OLE DB > Colonne de sortie > puis sélectionnez ItemCode et définissez la propriété SortKeyPosition sur 1 (en supposant que vous utilisez la source ASC dans l'instruction SQL).
  • Ensuite, ajoutez une jointure de fusion dans la tâche de flux de données. Cela nécessite que les deux entrées soient triées, c'est pourquoi les entrées sont maintenant triées. Vous pouvez le faire dans les deux cas, mais pour cet exemple, utilisez la source OLE DB qui ne sera utilisée que lorsque ItemCode n'existe pas en tant qu'entrée gauche de la jointure de fusion. Utilisez une jointure externe gauche et la colonne ItemCode comme clé de jointure en les connectant en faisant glisser une ligne de l'une à l'autre dans l'interface graphique. Ajoutez toutes les colonnes de la source OLE DB que vous souhaitez utiliser lorsque le même ItemCode est dans les deux ensembles de données (d'après ce que je pourrais dire, c'est Extraire les nouvelles données d'élément , veuillez l'ajuster si ce n'est pas le cas) en cochant la case à côté d'eux dans l'éditeur de jointure de fusion. Utilisez un préfixe d'alias de sortie qui vous aidera à les distinguer, par exemple X_ItemCode pour les lignes correspondantes.
  • Après la jointure de fusion, ajoutez un fractionnement conditionnel. Il s'agit de diviser les enregistrements selon que X_ItemCode a été trouvé. Pour l'expression de la première sortie, utilisez la fonction ISNULL pour tester s'il y avait une correspondance à partir de la jointure externe gauche. Par exemple, ISNULL (X_ItemCode)! = TRUE indique que le ItemCode existe dans les deux ensembles de données. Vous pouvez appeler cette sortie Lignes correspondantes . La sortie par défaut contiendra les non-correspondances. Pour faciliter la distinction, vous pouvez renommer la sortie par défaut Lignes sans correspondance .
  • Connectez la sortie Lignes correspondantes à la table de destination. Dans cette mappez uniquement les colonnes de lignes qui correspondaient pour la source que vous souhaitez utiliser lorsque le ItemCode existe dans les deux ensembles de données, c'est-à-dire le X_ des lignes préfixées telles que X_ItemCode .
  • Ajoutez une autre destination SQL Server dans le flux de données et connectez la sortie Lignes non correspondantes à celle-ci, avec toutes les colonnes mappées à partir des lignes qui ne correspondent pas , celui sans X_ dans cet exemple.
  • De retour sur le flux de contrôle dans le package, ajoutez une autre tâche de flux de données après celle-ci. Utilisez la table intermédiaire comme source OLE DB et la table de destination comme destination SQL Server. Le tri n'est pas nécessaire ici.

0 commentaires