6
votes

Besoin d'obtenir plusieurs valeurs à partir d'une table dans la jointure gauche

J'ai une table contenant les données ci-dessous.

Disons que j'ai deux versions du projet et que j'ai besoin de migrer les données d'une ancienne version vers une nouvelle version.

Disons tblFolders en version1

SELECT    id, 
      foldername, 
      b.version2userid AS createdby, 
      b.version2userid AS modifiedby 
FROM      tblfolders A WITH(nolock) 
LEFT JOIN tblusersmapping B WITH(nolock) 
ON        a.createdby = b.version1userid, 
          a.modifiedby = b.version1userid

Et une autre table ayant l'ID utilisateur des deux versions.

Disons son tblUsersMapping p>

SELECT id, 
   foldername, 
   B.version2userid AS CreatedBy
FROM   tblfolders A WITH(nolock) 
       LEFT JOIN tblusersmapping B WITH(nolock) 
              ON A.createdby = B.version1userid

Je dois maintenant transférer des données de la version 1 à la version 2. Lorsque je transfère des données, les identifiants Créé par et Modifié par doivent par de la nouvelle version.

Donc, même si j'ai des données comme ci-dessous

|  1 | SIMPLE     | 321          | 21           |

Il devrait être transféré comme ci-dessous

|  1 | SIMPLE     | 5            | 6            |


0 commentaires

6 Réponses :


2
votes

Si vous souhaitez remplir à la fois la colonne à laquelle chaque colonne se joint à une ligne différente, dans ce cas, vous devez joindre la même table deux fois comme suit. Vous ne pouvez pas l'obtenir avec une seule table jointe comme vous le souhaitez.

SELECT id, 
   foldername, 
   B.version2userid AS CreatedBy
   C.Version2UserID    AS ModifiedBy
FROM   tblfolders A WITH(nolock) 
       LEFT JOIN tblusersmapping B WITH(nolock) 
              ON A.createdby = B.version1userid
        LEFT JOIN tblusersmapping C WITH(nolock) 
              ON A.ModifiedBy    = C.version1userid


2 commentaires

Merci pour votre réponse. Avez-vous une autre solution dont je n'ai pas besoin et une autre jointure? Parce que comme mentionné dans la question, il peut y avoir plus de données de crore dans le tableau et une seule jointure est déjà un gros problème pour moi.


Dans votre scénario actuel, vous devez l'utiliser deux fois et c'est très courant. Si vos tables sont correctement indexées, vous ne devriez pas avoir de problèmes de performances.



3
votes

Vous pouvez utiliser la sélection multiple qui peut vous aider.

SELECT id, 
foldername, 
(SELECT version2userid from tblUsersMapping where Version1UserID=tblfolders.CreatedBy) AS CreatedBy,
(SELECT version2userid from tblUsersMapping where Version1UserID=tblfolders.ModifiedBy) AS ModifiedBy
FROM   tblfolders


2 commentaires

C'est une mauvaise idée car elle ralentira lorsque la table aura de nombreux enregistrements.


Oui, vous avez raison, en termes de performances, cela ralentira un peu.



2
votes

Essayez ceci, cela fonctionnera sur tous les exemples de données,

select tf.id,tf.FolderName
,oa.Version2UserID as CreatedBy
,oa1.Version2UserID as ModifiedBy
from @tblFolders tf
outer apply(select top 1 Version2UserID 
from @tblUsersMapping tu 
where tu.Version1UserID= tf.CreatedBy order by id desc)oa
outer apply(select top 1 Version2UserID 
from @tblUsersMapping tu 
where tu.Version1UserID= tf.ModifiedBy order by id desc)oa1


0 commentaires

2
votes

Vous pouvez utiliser UDF pour renvoyer modifiedby et INNER JOIN au lieu de LEFT JOIN (si l'exigence est remplie) comme ci-dessous. Je pense que cela aidera dans la préformance

id  foldername  createdby   modifiedby
1   SIMPLE      321         21
2   SIMPLE1     884         500

OUTPUT:

CREATE TABLE tblFolders (id INT, folderName VARCHAR(20), createdBy INT, modifiedBy INT)
INSERT INTO tblFolders VALUES
(1,'SIMPLE',     5,6),
(2,'SIMPLE1',    8,1)

CREATE TABLE tblUsersMapping(id INT, Version1UserID INT, Version2UserID INT)
INSERT INTO tblUsersMapping VALUES
(1,1,500),
(2,2,465),
(3,3,12),
(4,4,85),
(5,5,321),
(6,6,21),
(7,7,44),
(8,8,884)


SELECT a.id, 
      a.foldername, 
      b.version2userid AS createdby, 
      dbo.FNAReturnModifiedBy(a.modifiedBy) AS modifiedby 
FROM tblfolders A WITH(nolock) 
INNER JOIN tblusersmapping B WITH(nolock) ON a.createdby = b.version1userid

--Function
IF OBJECT_ID(N'dbo.FNAReturnModifiedBy', N'FN') IS NOT NULL
DROP FUNCTION dbo.FNAReturnModifiedBy
 GO 

CREATE FUNCTION dbo.FNAReturnModifiedBy(@updated_by INT)
RETURNS INT AS  
BEGIN 
    DECLARE @updateUserID INT
    SELECT @updateUserID = Version2UserID 
    FROM tblusersmapping WHERE Version1UserID = @updated_by

    RETURN @updateUserID
END


1 commentaires

Cela donne un résultat vraiment plus rapide. Il y a quelques incohérences dans le décompte par rapport à la jointure gauche, je vais donc vérifier cela et je dois également vérifier comment adapter cette requête dans mon code car j'ai tout le système dynamique et les requêtes sont créées de manière dynamique en fonction de la structure de la classe. Merci d'avoir répondu.



2
votes

Remarque:

  1. Je ne savais pas comment trouver les performances des requêtes. J'ai écrit uniquement pour votre sortie attendue.

  2. J'utilise SQL Server 2012.

  3. Je n'ai pas utilisé plus d'une jointure.

  4. La requête a effectué JOIN, GROUP BY, ROW_NUMBER (), CASE au lieu de deux LEFT JOIN

Entrée:

id      FolderName  Version1UserID  Version2UserID
1       SIMPLE      321             21
2       SIMPLE1     884             500
3       File        44              321

Requête:

select 
id, FolderName 
, max (case when rn = 1 then Version2UserID end) Version1UserID
, max (case when rn = 2 then Version2UserID end) Version2UserID
from (
 select 
  v.id, v.FolderName, u.Version1UserID, u.Version2UserID
  , ROW_NUMBER () over 
   (partition by v.id order by v.id, v.CreatedBy, 
    case 
     when v.CreatedBy > v.ModifiedBy then  u.Version1UserID 
    end desc
   ) rn 
  , v.CreatedBy, v.ModifiedBy
 from ##ver v 
 join ##veruser u 
 on u.Version1UserID in (v.CreatedBy, v.ModifiedBy)
) a 
group by id, FolderName 
order by id


0 commentaires

1
votes

Essayez celui-ci.

 Select a.id,folderName,b.Version2UserId as createdby,c.Version2UserId as modifiedby 
 from tblFolders as a WITH(nolock)
 inner join tblUsersMapping as b WITH(nolock) on a.createdby =b .Version1UserID 
 inner join tblUsersMapping as c WITH(nolock) on a.modifiedBy =c .Version1UserID


0 commentaires