2013-04-12 3 views
1

Problème avec une table USER_DIM dans une base de données qui contient des références à d'autres tables de cette base de données, telles que USER_ACTIVITY_FACT via USER_ID.Mise à jour SQL - fusion de données

Un problème se pose lorsque la conception d'origine de la table n'utilise pas un identificateur unique approprié qui provient en fait de l'EXTERNAL_ID d'une autre base de données.

Je peux comprendre comment sélectionner les lignes supplémentaires ou de les supprimer, mais je veux mettre à jour les lignes dans les autres tables pour pointer vers le USER_ID d'origine, puis supprimer les lignes supplémentaires dans la table USER_DIM

SELECT ACTIVITY_FACT.USER_ID 
FROM USER_ACTIVITY_FACT 
WHERE USER_ACTIVITY_FACT.USER_ID IN (
select USER_ID  
    FROM USER_DIM 
    WHERE EXTERNAL_ID IN (SELECT ud2.EXTERNAL_ID 
    FROM USER_DIM as ud2 
    where USER_ID > ud2.USER_ID)); 

les mettre à jour pour être le plus petit USER_ID

Ensuite, exécutez l'instruction delete sur USER_DIM; Après quoi ALTER la table pour avoir un index unique sur la colonne EXTERNAL_ID.

Cette requête peut être mise à jour par ligne plutôt que de mettre à jour plusieurs lignes à la fois pour l'utilisateur USER_ID incriminé.

Merci d'avance pour votre aide!

MISE À JOUR Pour clarifier l'objectif:

USER_ACTIVITY_FACT 
------------- 
USER_ID 
2 
3 
4 
5 
6 

USER_DIM 
-------------- 
USER_ID EXTERNAL_ID 
2  23 
3  23 
4  24 
5  24 
6  26 

..result devrait ressembler à

USER_ACTIVITY_FACT 
------------- 
USER_ID 
2 
2 
4 
4 
6 

USER_DIM 
-------------- 
USER_ID EXTERNAL_ID 
2  23 
4  24 
6  26 

espérons que cette aide

Répondre

1

Je ne sais pas si je suis bien, mais ici la demande est quelque chose que je suis venu avec. Vous pouvez utiliser group by pour trouver votre USER_ID minimum pour chaque EXTERNAL_ID et le mettre dans la table temporaire comme information de mappage (OLD_ID => NEW_ID). Ensuite, vous rejoignez vos tables qui ont besoin d'être mises à jour sur la table temporaire et de les mettre à jour de l'ancien vers le nouvel identifiant (Join on OLD_ID, Update to NEW_ID). À la fin, vous pouvez supprimer comme vous le faisiez, ou encore vous joindre à la table de mappage.

Vous pouvez vérifier SQLFiddleDemo

--prepare data and insert into #mapping temp table from dim 
WITH CTE1 AS 
(
    SELECT EXTERNAL_ID, MIN(USER_ID) AS NEW_USER_ID 
    FROM dbo.USER_DIM 
    GROUP BY EXTERNAL_ID 
) 
SELECT CTE1.EXTERNAL_ID , 
     USER_ID AS OLD_USER_ID , 
     NEW_USER_ID 
INTO #mapping 
FROM dbo.USER_DIM 
INNER JOIN CTE1 ON dbo.USER_DIM.EXTERNAL_ID = CTE1.EXTERNAL_ID; 

--check your mappings 
SELECT * FROM #mapping; 

--update fact table based on join on mappings 
UPDATE fact 
SET fact.USER_ID = src.NEW_USER_ID 
FROM #mapping src 
INNER JOIN dbo.USER_ACTIVITY_FACT fact ON src.OLD_USER_ID = fact.USER_ID; 

--check your fact table 
SELECT * FROM USER_ACTIVITY_FACT; 

--delete from dim based on mappings missmatch 
DELETE d 
FROM dbo.USER_DIM d 
INNER JOIN #mapping m ON d.USER_ID = m.OLD_USER_ID 
WHERE m.NEW_USER_ID <> m.OLD_USER_ID; 

--check your dim table 
SELECT * FROM dbo.USER_DIM; 
1

Utilisez Mise à jour à partir d'une table dérivée avec OUTPUT clause

DECLARE @delUserID TABLE(delUserID int) 

UPDATE x 
SET x.USER_ID = x.NewUserID 
OUTPUT DELETED.USER_ID INTO @delUserID 
FROM ( 
     SELECT f.USER_ID, 
      MIN(f.USER_ID) OVER(PARTITION BY u.EXTERNAL_ID) AS NewUserID    
     FROM dbo.USER_ATIVITY_FACT f JOIN dbo.USER_DIM u ON f.USER_ID = u.USER_ID 
    ) x 
WHERE x.USER_ID != x.NewUserID  

DELETE USER_DIM 
WHERE USER_ID IN (SELECT delUserID FROM @delUserID) 

Démo SQLFiddle

0

Voici ce que je suis venu avec. Les solutions de @Nenad fonctionnent mais je dois pousser cela à travers des scripts de liquibase et je ne savais pas si les fonctions de SQL Server fonctionneraient. J'ai vérifié cela aussi contre SQLFiddle ainsi.

--prepare data and insert into #mapping temp table from dim 
UPDATE USER_ACTIVITY_FACT 
SET 
    USER_ID = (SELECT 
      MIN(ud1.USER_ID) 
     FROM 
      USER_DIM as ud1 
     WHERE 
      ud1.EXTERNAL_ID = (SELECT 
        MIN(ud2.EXTERNAL_ID) 
       FROM 
        USER_DIM as ud2, 
        USER_DIM as ud3 
       WHERE 
        ud2.EXTERNAL_ID = ud3.EXTERNAL_ID 
         AND ud3.USER_ID = USER_ACTIVITY_FACT.USER_ID) 
); 

--delete from dim based on mappings missmatch 
DELETE  
    FROM USER_DIM 
WHERE EXISTS 
    (SELECT * FROM USER_DIM t1 
    WHERE t1.EXTERNAL_ID = USER_DIM.EXTERNAL_ID 
AND USER_DIM.USER_ID > t1.USER_ID);