使用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
因此,我正在尝试根据某些匹配条件,在同一人的另一个系统中搜索:
下面是查询的一部分,该查询使用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等,因此必须确保检查可能的匹配项。
如果找到匹配项,我希望它“执行某些操作”。我希望它能够引用第一个表中的照片路径列。所以我需要以某种方式将其传递给“做某事”部分。
答案 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>
无论“执行某项操作”中的内容是什么,在任何情况下都应尝试以批量方式进行操作-跳过任何类型的循环,例如WHILE
或CURSOR
。
希望这会有所帮助。
答案 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