需要从左联接的表中获取多个值

时间:2019-01-22 06:00:47

标签: sql sql-server migration left-join

我有一个表,其数据如下。

说我有两个版本的项目,我需要将数据从旧版本迁移到新版本。

让我们在版本1中说tblFolders

+----+------------+--------------+--------------+
| id | FolderName | CreatedBy    | ModifiedBy   |
+----+------------+--------------+--------------+
|  1 | SIMPLE     | 5            | 6            |
|  2 | SIMPLE1    | 8            | 1            |
+----+------------+--------------+--------------+

和另一个具有两个版本的用户名的表。

我们假设其tblUsersMapping

+----+----------------+-------------------+
| id | Version1UserID | Version2UserID    |
+----+----------------+-------------------+
|  1 | 1              | 500               |
|  2 | 2              | 465               |
|  3 | 3              | 12                |
|  4 | 4              | 85                |
|  5 | 5              | 321               |
|  6 | 6              | 21                |
|  7 | 7              | 44                |
|  8 | 8              | 884               |
+----+----------------+-------------------+

现在我需要将数据从版本1传输到版本2。当我传输数据时, CreatedBy Modifiedby ID应该是新版本的。

所以尽管我有以下数据

|  1 | SIMPLE     | 5            | 6            |

应按以下方式转移

|  1 | SIMPLE     | 321          | 21           |

为此,到目前为止,我在这两个表之间添加了一个联接,如下所示。

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

这将为列 CreatedBy 提供适当的结果。

但是如何从tblUsersMapping的ModifiedBy列获取用户ID? 下面的操作将不起作用,并且两列都将为NULL。

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

一种方法是我可以使用tblusersmapping表添加另一个联接。但这不是一个好主意,因为表可能具有大量数据,而另一个联接会影响查询的性能。

我的问题是如何从基于createdby和Modifyed列的映射表中获取Version1UserID和Version2UserID?

6 个答案:

答案 0 :(得分:3)

您可以使用多项选择来帮助您。

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

答案 1 :(得分:2)

如果您想同时填充每一列所连接到的两列到不同的行,那么在这种情况下,您必须将同一张表连接两次,如下所示。您无法通过单个表联接来实现它。

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 :(得分:2)

尝试一下,它将适用于所有示例数据,

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

答案 3 :(得分:2)

您可以使用UDF返回modifiedbyINNER JOIN而不是LEFT JOIN(如果满足要求),如下所示。我认为这对表演有帮助

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

输出:

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

答案 4 :(得分:2)

注意:

  1. 我不知道如何查找查询性能。我只为您的预期输出而写。

  2. 我正在使用SQL Server 2012。

  3. 我没有使用多个Join。

  4. 查询执行了JOIN, GROUP BY, ROW_NUMBER (), CASE,而不是两个LEFT JOIN

输入:

create table ##ver (id int,  FolderName varchar (10), CreatedBy     int, ModifiedBy   int)

insert into ##ver values 
 (1,'SIMPLE',5,6)
,(2,'SIMPLE1',8,1)
,(3,'File',7, 5)

select * from ##ver

create table ##veruser (id int,  Version1UserID  int, Version2UserID    int)

insert into ##veruser 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 * from ##veruser 

查询:

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

更新1:

查询:

  1. 加入表格。

    行号,在()上方,

    按ID分区。

    按文件ID(v.id)排序,创建者ID递增,如果创建者ID更大 比修改过的ID少,然后创建者ID降序。 (由于第二步,必须重新排序)

  2. 取决于'rn'值,行将转移到列

(您可以在here上找到很多示例)

输出:

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

答案 5 :(得分:1)

尝试这个。

 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