SQL Server:在查询的每一行上运行查询,以在另一个表中找到匹配项

时间:2018-09-12 14:15:05

标签: sql sql-server

使用SQL Server,我要查询从一个系统拍摄的人物和照片的列表。同一个人可以有多张照片。这些属性是名字,姓氏,出生日期,SSN等...

SELECT * 
FROM MASTERPHOTOSDB

输出:

Master  | PhotoPath  | AQUIRE_TM | LastName | FirstName  | MiddleName | DOB      | DL
471578  | PHOTO72044 |1899-12-30 | PEREZ    | JOSE       | C          |4/15/2000 |TX12345678
468893  | PHOTO72049 |1899-12-30 | JOHNSON  | TRENT      |            |          |TX87654321
56553   | PHOTO72055 |1899-12-30 | SMITH    | JOHN       | D          |1/1/1990  |TX11223344
56553   | PHOTO72056 |1899-12-30 | SMITH    | JOHN       | D          |1/1/1990  |TX11223344 

因此,我正在尝试根据某些匹配条件,在同一人的另一个系统中搜索:

  1. 姓氏,名字,中间名,DOB,DL(如果不匹配,请转到2)
  2. 姓氏,名字,DOB,DL(如果不匹配,则转到3)
  3. 姓氏,名字,SSN等(如果没有匹配的结尾搜索,请转到下一张照片)

下面是查询的一部分,该查询使用IF语句查找匹配项(只是整个查询的一个示例):

 IF (SELECT TOP (1) COUNT(*)
     FROM [InformHelper].[dbo].[InformMasterNamesTST]
     WHERE [LastName] = 'SMITH' 
       AND [FirstName] = 'JOHN' 
       AND DOB = '01/01/1990' 
       AND DL = 'TX12345678') > 0    
    SELECT TOP (1) *
    FROM [InformHelper].[dbo].[InformMasterNamesTST]
    WHERE [LastName] = 'SMITH' 
      AND [FirstName] = 'JOHN' 
      AND DOB = '01/01/1990' 
      AND DL = 'TX12345678') > 0    
    ORDER BY [NamelastUpdated] DESC, [NameEnterDate] DESC
ELSE IF (SELECT TOP (1) COUNT(*)
         FROM [InformHelper].[dbo].[InformMasterNamesTST]
     WHERE [LastName] = 'SMITH' 
       AND [FirstName] = 'JOHN' 
       AND DOB = '01/01/1990' 
       AND SSN = '12345678901') > 0      
    SELECT TOP (1) *
    FROM [InformHelper].[dbo].[InformMasterNamesTST]
    WHERE [LastName] = 'SMITH' 
      AND [FirstName] = 'JOHN' 
      AND DOB = '01/01/1990' 
      AND SSN = '12345678901') > 0      
    ORDER BY [NamelastUpdated] DESC, [NameEnterDate] DESC
ELSE 
    SELECT 0

哪个将从我的第二个表中返回以下内容:

Name     | LastName | FirstName | MiddleName | SEX | RACE | DOB         | DL | SSN
10173538  | SMITH    | JOHN      | SHAWN      | M   | W    | 01/01/1990 |     | 1234567890

基本上,我希望它对第一个表中的每个名称进行“ for each”搜索我创建的IF语句。我对如何查询IF语句中的每个名称感到困惑。由于某些名称没有DL,SSN,中间名,DOB等,因此必须确保检查可能的匹配项。

如果找到匹配项,我希望它“执行某些操作”。我希望它能够引用第一个表中的照片路径列。所以我需要以某种方式将其传递给“做某事”部分。

4 个答案:

答案 0 :(得分:0)

我认为您可以通过COALESCE和三个联接来完成您想要的事情 COALESCE基本上会查找第一个非NULL项,因此,如果连接失败,它将转到下一个

SQL看起来像

  SELECT
     Name           = COALESCE(S1.Name, S2.Name, S3.Name)
     LastName       = COALESCE(S1.LastName, S2.LastName, S3.LastName)
     FirstName      = COALESCE(S1.FirstName, S2.FirstName, S3.FirstName)
     MiddleName     = COALESCE(S1.MiddleName, S2.MiddleName, S3.MiddleName)
     SEX            = COALESCE(S1.SEX, S2.SEX, S3.SEX)
     RACE           = COALESCE(S1.RACE, S2.RACE, S3.RACE)
     DOB            = COALESCE(S1.DOB, S2.DOB, S3.DOB)
     DL             = COALESCE(S1.DL, S2.DL, S3.DL)
     SSN            = COALESCE(S1.SSN, S2.SSN, S3.SSN)
  FROM MASTERPHOTODB MPDB

  LEFT JOIN SECONDSYSTEM S1
    ON  S1.LastName     = MPDB.LastName
    AND S1.FirstName    = MPDB.FirstName
    AND S1.MiddleName   = MPDB.MiddleName
    AND S1.DOV          = MPDB.DOB
    AND S1.DL           = MPDB.DL


  LEFT JOIN SECONDSYSTEM S2
    ON  S2.LastName     = MPDB.LastName
    AND S2.FirstName    = MPDB.FirstName
    AND S2.DOB          = MPDB.DOB
    AND S2.DL           = MPDB.DL

  LEFT JOIN SECONDSYSTEM S3
    ON  S3.LastName     = MPDB.LastName
    AND S3.FirstName    = MPDB.FirstName
    AND S3.SSN          = MPDB.SSN

  WHERE 1=1
    AND MPDB.LastName = 'SMITH'
    AND MPDB.FirstName = 'JOHN'
    AND MPDB.DOB = '01/01/1990' 
    AND MPDB.DL = 'TX12345678'

应该为您提供数据集,然后您需要游标返回的元素

答案 1 :(得分:0)

我会提出类似的建议,但是不确定我是否完全理解您的想法。请添加更多输入,如有必要,我将更新我的答案。 总的来说,我想通过各种搜索条件来唯一地识别所有人,然后对他们进行“操作”:

DECLARE @userUniqueIDs TABLE (UniqueId NVARCHAR(100)); --could be multiple values of any data type
INSERT @userUniqueIDs
SELECT UniqueId
FROM MASTERPHOTOSDB MPDB
JOIN [InformHelper].[dbo].[InformMasterNamesTST] IMNTST 
ON <SearchCondition_1>;

INSERT @userUniqueIDs
SELECT UniqueId
FROM MASTERPHOTOSDB MPDB
JOIN [InformHelper].[dbo].[InformMasterNamesTST] IMNTST 
ON <SearchCondition_2>
WHERE UniqueId NOT IN (SELECT UniqueId FROM @userUniqueIDs);

INSERT @userUniqueIDs
SELECT UniqueId
FROM MASTERPHOTOSDB MPDB
JOIN [InformHelper].[dbo].[InformMasterNamesTST] IMNTST 
ON <SearchCondition_3>
WHERE UniqueId NOT IN (SELECT UniqueId FROM @userUniqueIDs);

<do_something with identified people>

无论“执行某项操作”中的内容是什么,在任何情况下都应尝试以批量方式进行操作-跳过任何类型的循环,例如WHILECURSOR

希望这会有所帮助。

答案 2 :(得分:0)

我可能会在您的输出中使用CASE语句来确定谁匹配另一个系统中的条件。

下面是一个基于Oracle的模拟示例,但是只需删除FROM DUAL类型语句,您还将了解它在SQL Server中的工作原理。

;WITH Data AS (
SELECT 471578 AS Master,  'PHOTO72044' AS PhotoPath,  '1899-12-30' AS AQUIRE_TM,  'PEREZ' AS LastName, 'JOSE' AS FirstName,  'C' AS MiddleName, '4/15/2000' AS DOB, 'TX12345678' AS DL FROM DUAL UNION ALL
SELECT 468893, 'PHOTO72049', '1899-12-30', 'JOHNSON', 'TRENT', '', '', 'TX87654321' FROM DUAL UNION ALL
SELECT 56553, 'PHOTO72055', '1899-12-30', 'SMITH', 'JOHN', 'D', '1/1/1990', 'TX11223344' FROM DUAL UNION ALL
SELECT 56553, 'PHOTO72056', '1899-12-30', 'SMITH', 'JOHN', 'D', '1/1/1990', 'TX11223344' FROM DUAL  
), MockOtherDataSource AS (
SELECT 471578 AS Master,  'PHOTO72044' AS PhotoPath,  '1899-12-30' AS AQUIRE_TM,  'PEREZ' AS LastName, 'JOSE' AS FirstName,  'C' AS MiddleName, '4/15/2000' AS DOB, 'TX12345678' AS DL FROM DUAL UNION ALL
SELECT 468893, 'PHOTO72049', '1899-12-30', 'JOHNSON', 'TRENT', '', '', 'TX87654321' FROM DUAL UNION ALL
SELECT 56553, 'PHOTO72055', '1899-12-30', 'SMITHY', 'JOHN', 'D', '1/1/1990', 'TX11223344' FROM DUAL UNION ALL
SELECT 56553, 'PHOTO72056', '1899-12-30', 'SMITH', 'JOHN', 'D', '1/1/1990', 'TX11223344' FROM DUAL UNION ALL
SELECT 56553, 'PHOTO72056', '1899-12-30', 'SMITH', 'JOHN', 'B', '1/1/1990', 'TX11223344' FROM DUAL  
), Combined AS (
SELECT 
    Data.Master,
    Data.PhotoPath,
    Data.FirstName,
    Data.MiddleName,
    Data.LastName, 
    Data.DL,
    CASE 
        -- Here is where you add your conditions to determine the "Match Type" 
        WHEN Data.FirstName = MockOtherDataSource.FirstName AND
             Data.LastName = MockOtherDataSource.LastName AND
             Data.MiddleName = MockOtherDataSource.MiddleName AND
             Data.DOB = MockOtherDataSource.DOB AND
             Data.DL = MockOtherDataSource.DL THEN 1
        WHEN Data.FirstName = MockOtherDataSource.FirstName AND
             Data.LastName = MockOtherDataSource.LastName AND
             Data.DOB = MockOtherDataSource.DOB AND
             Data.DL = MockOtherDataSource.DL AND 
             (Data.MiddleName <> MockOtherDataSource.MiddleName 
              OR (Data.MiddleName IS NULL AND MockOtherDataSource.MiddleName IS NOT NULL) 
              OR (Data.MiddleName IS NOT NULL AND MockOtherDataSource.MiddleName IS NULL)) THEN 2
        -- Similar match conditions here for other join conditions you're interested in
    END AS MatchType,
    MockOtherDataSource.Master AS Master1,
    MockOtherDataSource.PhotoPath AS PhotoPath1,
    MockOtherDataSource.FirstName AS FirstName1,
    MockOtherDataSource.MiddleName AS MiddleName1,
    MockOtherDataSource.LastName AS LastName1, 
    MockOtherDataSource.DL AS DL1
FROM 
    Data,
    MockOtherDataSource
) SELECT * FROM Combined WHERE MatchType IS NOT NULL
;

答案 3 :(得分:0)

从建议的内容出发:

DECLARE @userUniqueIDs TABLE (Inform_MasterName NVARCHAR(100), PhotoPath NVARCHAR(100)); --could be multiple values of any data type
INSERT @userUniqueIDs
SELECT IMNTST.Inform_MasterName, MPDB.PhotoPath
FROM [InformHelper].[dbo].[LTMasterNamesAndPhotosYesterday] MPDB
JOIN [InformHelper].[dbo].[InformMasterNamesTST] IMNTST 
ON  IMNTST.LastName     = MPDB.LastName collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.MiddleName    = MPDB.MiddleName collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.FirstName    = MPDB.FirstName collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.SEX          = MPDB.SEX collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.RACE           = MPDB.RACE collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.DOB          = MPDB.DOB collate SQL_Latin1_General_CP1_CI_AS 


INSERT @userUniqueIDs
SELECT Inform_MasterName, MPDB.PhotoPath
FROM [InformHelper].[dbo].[LTMasterNamesAndPhotosYesterday] MPDB
JOIN [InformHelper].[dbo].[InformMasterNamesTST] IMNTST 
ON  IMNTST.LastName     = MPDB.LastName collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.FirstName    = MPDB.FirstName collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.SEX          = MPDB.SEX collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.RACE           = MPDB.RACE collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.DL           = MPDB.DL collate SQL_Latin1_General_CP1_CI_AS 
WHERE Inform_MasterName NOT IN (SELECT Inform_MasterName FROM @userUniqueIDs);

INSERT @userUniqueIDs
SELECT Inform_MasterName, MPDB.PhotoPath
FROM [InformHelper].[dbo].[LTMasterNamesAndPhotosYesterday] MPDB
JOIN [InformHelper].[dbo].[InformMasterNamesTST] IMNTST 
ON  IMNTST.LastName     = MPDB.LastName collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.FirstName    = MPDB.FirstName collate SQL_Latin1_General_CP1_CI_AS
    AND IMNTST.DL           = MPDB.DL collate SQL_Latin1_General_CP1_CI_AS
    AND IMNTST.DOB          = MPDB.DOB collate SQL_Latin1_General_CP1_CI_AS 
WHERE Inform_MasterName NOT IN (SELECT Inform_MasterName FROM @userUniqueIDs);

INSERT @userUniqueIDs
SELECT Inform_MasterName, MPDB.PhotoPath
FROM [InformHelper].[dbo].[LTMasterNamesAndPhotosYesterday] MPDB
JOIN [InformHelper].[dbo].[InformMasterNamesTST] IMNTST 
ON  IMNTST.LastName     = MPDB.LastName collate SQL_Latin1_General_CP1_CI_AS 
    AND IMNTST.SSN           = MPDB.SSN collate SQL_Latin1_General_CP1_CI_AS
    AND IMNTST.DOB          = MPDB.DOB collate SQL_Latin1_General_CP1_CI_AS 
WHERE Inform_MasterName NOT IN (SELECT Inform_MasterName FROM @userUniqueIDs);

我确实必须从PhotoPath列中找到唯一的值,因为在某些情况下,PhotoPath中存在重复项。我使用了以下内容:

select Inform_MasterName,
       PhotoPath
from (
SELECT Inform_MasterName,
       PhotoPath,
       ROW_NUMBER()OVER(PARTITION BY PhotoPath ORDER BY Inform_MasterName DESC) rn
       from @userUniqueIDs
       ) a 
       where rn = 1

输出:

**Inform_MasterName | PhotoPath**
21911               | L:\Images\57114.JPG                               
210392              | L:\Images\57115.JPG                               
79489               | L:\Images\PHOTO72431.jpg                          
19975               | L:\Images\PHOTO72499.jpg                          
111132              | L:\Images\PHOTO72509.jpg                          
105377              | L:\Images\PHOTO72510.jpg                          
10230182            | L:\Images\PHOTO72529.jpg                          
37933               | L:\Images\PHOTO72533.jpg                          
36966               | L:\Images\PHOTO72540.jpg                          
10223896            | L:\Images\PHOTO72550.jpg                          
10223896            | L:\Images\PHOTO72551.jpg