T-SQL准备动态合并
T-SQL prepare dynamic COALESCE
如截图所附,有两个table。
- 配置:
- 详情
使用 Configuration
和 Detail
table 我想在 Detail
table 中填充 IdentificationType
和 IDerivedIdentification
列].
推导以上列时应使用以下逻辑
Configuration
table 具有优先顺序,用户可以动态更改(即,如果国家/地区是 Austria
,则 ID 优先顺序应为 LEI,然后是 TIN(在case LEI 为空)然后 CONCAT(如果都为空则为其他逻辑)
如果contract ID = 3,country是BG,那么首先要检查LEI,因为它是NULL,所以会选择CCPT = 456。
如果允许硬编码,我可以使用 COALESCE
和 CASE
语句。
能否请您提出任何替代方法?
此致
迪甘特
假设这是一些可怕的数据转储,而您正试图在此处清理它是一些 SQL 扔给它的东西。 :) 首先,我能够通过 Adobe Acrobat > Excel 捕获您的图像文本。
(我还在以下位置为您构建了架构:http://sqlfiddle.com/#!6/8f404/12)
首先,正确的做法是解决明显的问题,那就是 table 结构。假设你不能,这里有一个解决方案。
所以,它就是这样,它所做的是从详细信息 table 以及配置 table.基本上,这样做有助于规范化数据,但如果没有修复数据结构的计划或者您不能这样做,它会降低您的主要性能。之后你只需加入 tables Detail.ContactId
到 DerivedTypes.ContactId
然后 DerivedPrefs.ISOCountryCode
到 Detail.CountrylSOCountryCode
和 DerivedTypes.ldentificationType = DerivedPrefs.ldentificationType
如果你使用内部连接而不是左连接您可以删除 RANK()
函数,但它不会显示所有 ContactId,仅显示在其 LEI、NIND、CCPT 或 TIN 列中具有值的那些。我认为无论如何这是一个更好的解决方案,因为您为什么要在报告中看到错误?为那些在这些列中没有值的人写一份单独的报告。最后,TOP (1) with ties
允许您为每个 ContactId 显示一条记录,并允许仍然显示有错误的记录。希望这会有所帮助。
CREATE TABLE Configuration
(ISOCountryCode varchar(2), CountryName varchar(8), FirstPref varchar(6), SecondPref varchar(6), ThirdPref varchar(6))
;
INSERT INTO Configuration
(ISOCountryCode, CountryName, FirstPref, SecondPref, ThirdPref)
VALUES
('AT', 'Austria', 'LEI', 'TIN', 'CONCAT'),
('BE', 'Belgium', 'LEI', 'NIND', 'CONCAT'),
('BG', 'Bulgaria', 'LEI', 'CCPT', 'CONCAT'),
('CY', 'Cyprus', 'LEI', 'NIND', 'CONCAT')
;
CREATE TABLE Detail
(ContactId int, FirstName varchar(1), LastName varchar(3), BirthDate varchar(4), CountrylSOCountryCode varchar(2), Nationality varchar(2), LEI varchar(9), NIND varchar(9), CCPT varchar(9), TIN varchar(9))
;
INSERT INTO Detail
(ContactId, FirstName, LastName, BirthDate, CountrylSOCountryCode, Nationality, LEI, NIND, CCPT, TIN)
VALUES
(1, 'A', 'DES', NULL, 'AT', 'AT', '123', '4345', NULL, NULL),
(2, 'B', 'DEG', NULL, 'BE', 'BE', NULL, '890', NULL, NULL),
(3, 'C', 'DEH', NULL, 'BG', 'BG', NULL, '123', '456', NULL),
(4, 'D', 'DEi', NULL, 'BG', 'BG', NULL, NULL, NULL, NULL)
;
SELECT TOP (1) with ties Detail.ContactId,
FirstName,
LastName,
BirthDate,
CountrylSOCountryCode,
Nationality,
LEI,
NIND,
CCPT,
TIN,
ISNULL(DerivedPrefs.ldentificationType, 'ERROR') ldentificationType,
IDerivedIdentification,
RANK() OVER (PARTITION BY Detail.ContactId ORDER BY
CASE WHEN Pref = 'FirstPref' THEN 1
WHEN Pref = 'SecondPref' THEN 2
WHEN Pref = 'ThirdPref' THEN 3
ELSE 99 END) AS PrefRank
FROM
Detail
LEFT JOIN
(
SELECT
ContactId,
LEI,
NIND,
CCPT,
TIN
FROM Detail
) DetailUNPVT
UNPIVOT
(IDerivedIdentification FOR ldentificationType IN
(LEI, NIND, CCPT, TIN)
)AS DerivedTypes
ON DerivedTypes.ContactId = Detail.ContactId
LEFT JOIN
(
SELECT
ISOCountryCode,
CountryName,
FirstPref,
SecondPref,
ThirdPref
FROM
Configuration
) ConfigUNPIVOT
UNPIVOT
(ldentificationType FOR Pref IN
(FirstPref, SecondPref, ThirdPref)
)AS DerivedPrefs
ON DerivedPrefs.ISOCountryCode = Detail.CountrylSOCountryCode
and DerivedTypes.ldentificationType = DerivedPrefs.ldentificationType
ORDER BY RANK() OVER (PARTITION BY Detail.ContactId ORDER BY
CASE WHEN Pref = 'FirstPref' THEN 1
WHEN Pref = 'SecondPref' THEN 2
WHEN Pref = 'ThirdPref' THEN 3
ELSE 99 END)
如截图所附,有两个table。
- 配置:
- 详情
使用 Configuration
和 Detail
table 我想在 Detail
table 中填充 IdentificationType
和 IDerivedIdentification
列].
推导以上列时应使用以下逻辑
Configuration
table 具有优先顺序,用户可以动态更改(即,如果国家/地区是Austria
,则 ID 优先顺序应为 LEI,然后是 TIN(在case LEI 为空)然后 CONCAT(如果都为空则为其他逻辑)如果contract ID = 3,country是BG,那么首先要检查LEI,因为它是NULL,所以会选择CCPT = 456。
如果允许硬编码,我可以使用 COALESCE
和 CASE
语句。
能否请您提出任何替代方法?
此致
迪甘特
假设这是一些可怕的数据转储,而您正试图在此处清理它是一些 SQL 扔给它的东西。 :) 首先,我能够通过 Adobe Acrobat > Excel 捕获您的图像文本。
(我还在以下位置为您构建了架构:http://sqlfiddle.com/#!6/8f404/12)
首先,正确的做法是解决明显的问题,那就是 table 结构。假设你不能,这里有一个解决方案。
所以,它就是这样,它所做的是从详细信息 table 以及配置 table.基本上,这样做有助于规范化数据,但如果没有修复数据结构的计划或者您不能这样做,它会降低您的主要性能。之后你只需加入 tables Detail.ContactId
到 DerivedTypes.ContactId
然后 DerivedPrefs.ISOCountryCode
到 Detail.CountrylSOCountryCode
和 DerivedTypes.ldentificationType = DerivedPrefs.ldentificationType
如果你使用内部连接而不是左连接您可以删除 RANK()
函数,但它不会显示所有 ContactId,仅显示在其 LEI、NIND、CCPT 或 TIN 列中具有值的那些。我认为无论如何这是一个更好的解决方案,因为您为什么要在报告中看到错误?为那些在这些列中没有值的人写一份单独的报告。最后,TOP (1) with ties
允许您为每个 ContactId 显示一条记录,并允许仍然显示有错误的记录。希望这会有所帮助。
CREATE TABLE Configuration
(ISOCountryCode varchar(2), CountryName varchar(8), FirstPref varchar(6), SecondPref varchar(6), ThirdPref varchar(6))
;
INSERT INTO Configuration
(ISOCountryCode, CountryName, FirstPref, SecondPref, ThirdPref)
VALUES
('AT', 'Austria', 'LEI', 'TIN', 'CONCAT'),
('BE', 'Belgium', 'LEI', 'NIND', 'CONCAT'),
('BG', 'Bulgaria', 'LEI', 'CCPT', 'CONCAT'),
('CY', 'Cyprus', 'LEI', 'NIND', 'CONCAT')
;
CREATE TABLE Detail
(ContactId int, FirstName varchar(1), LastName varchar(3), BirthDate varchar(4), CountrylSOCountryCode varchar(2), Nationality varchar(2), LEI varchar(9), NIND varchar(9), CCPT varchar(9), TIN varchar(9))
;
INSERT INTO Detail
(ContactId, FirstName, LastName, BirthDate, CountrylSOCountryCode, Nationality, LEI, NIND, CCPT, TIN)
VALUES
(1, 'A', 'DES', NULL, 'AT', 'AT', '123', '4345', NULL, NULL),
(2, 'B', 'DEG', NULL, 'BE', 'BE', NULL, '890', NULL, NULL),
(3, 'C', 'DEH', NULL, 'BG', 'BG', NULL, '123', '456', NULL),
(4, 'D', 'DEi', NULL, 'BG', 'BG', NULL, NULL, NULL, NULL)
;
SELECT TOP (1) with ties Detail.ContactId,
FirstName,
LastName,
BirthDate,
CountrylSOCountryCode,
Nationality,
LEI,
NIND,
CCPT,
TIN,
ISNULL(DerivedPrefs.ldentificationType, 'ERROR') ldentificationType,
IDerivedIdentification,
RANK() OVER (PARTITION BY Detail.ContactId ORDER BY
CASE WHEN Pref = 'FirstPref' THEN 1
WHEN Pref = 'SecondPref' THEN 2
WHEN Pref = 'ThirdPref' THEN 3
ELSE 99 END) AS PrefRank
FROM
Detail
LEFT JOIN
(
SELECT
ContactId,
LEI,
NIND,
CCPT,
TIN
FROM Detail
) DetailUNPVT
UNPIVOT
(IDerivedIdentification FOR ldentificationType IN
(LEI, NIND, CCPT, TIN)
)AS DerivedTypes
ON DerivedTypes.ContactId = Detail.ContactId
LEFT JOIN
(
SELECT
ISOCountryCode,
CountryName,
FirstPref,
SecondPref,
ThirdPref
FROM
Configuration
) ConfigUNPIVOT
UNPIVOT
(ldentificationType FOR Pref IN
(FirstPref, SecondPref, ThirdPref)
)AS DerivedPrefs
ON DerivedPrefs.ISOCountryCode = Detail.CountrylSOCountryCode
and DerivedTypes.ldentificationType = DerivedPrefs.ldentificationType
ORDER BY RANK() OVER (PARTITION BY Detail.ContactId ORDER BY
CASE WHEN Pref = 'FirstPref' THEN 1
WHEN Pref = 'SecondPref' THEN 2
WHEN Pref = 'ThirdPref' THEN 3
ELSE 99 END)