Sql 查询以根据特定列中的值相互比较表中的值,并仅显示忽略空值的差异
我有一个数据表,显示不同位置使用的不同代码和描述。我需要将这些位置合并为一个。在这样做之前,我需要能够清楚地看到两组数据,一组是用于给定位置的给定类别中的代码的不同描述,另一组是用于给定位置的给定类别中的描述的不同代码,这样我才能使数据一致。虽然给定的代码在每个位置的每个类别中只有一个描述,但给定的描述在每个位置的每个类别中可以有多个代码。我只关心不同地点使用不同代码和类别的情况。出于这些目的,在一个或多个位置相同但在其他位置未使用的代码或描述没有区别 我需要能够运行一个查询,为给定的类别和代码显示按位置列出的所有描述,包括未使用该代码的空值,所有位置的描述都不相同。同样,如果代码除了null之外没有其他差异,那么它不应该在列表中 我需要能够运行另一个查询,该查询将按位置显示给定类别和描述的所有代码,包括未使用该描述的空代码,所有位置的代码不相同,请记住每个位置可能有多个代码。同样如上所述,如果给定类别和描述的代码相同,但并非在所有位置都使用,则不应返回该代码 因此,如果我的表有:Sql 查询以根据特定列中的值相互比较表中的值,并仅显示忽略空值的差异,sql,sql-server,Sql,Sql Server,我有一个数据表,显示不同位置使用的不同代码和描述。我需要将这些位置合并为一个。在这样做之前,我需要能够清楚地看到两组数据,一组是用于给定位置的给定类别中的代码的不同描述,另一组是用于给定位置的给定类别中的描述的不同代码,这样我才能使数据一致。虽然给定的代码在每个位置的每个类别中只有一个描述,但给定的描述在每个位置的每个类别中可以有多个代码。我只关心不同地点使用不同代码和类别的情况。出于这些目的,在一个或多个位置相同但在其他位置未使用的代码或描述没有区别 我需要能够运行一个查询,为给定的类别和代码
LOCATION CATEGORY CODE DESCR
aaa Dept 001 Pharmacy
bbb Dept 001 Pharmacy
ccc Dept 002 Pharmacy
ddd Dept 002 Labratory
aaa Dept 003 Clerical
bbb Dept 003 Laundry
ccc Dept 003 IT
ddd Dept 003 Accounting
aaa Dept 004 Purchasing
bbb Dept 004 Purchasing
ccc Dept 004 Purchasing
ddd Dept 004 Purchasing
aaa Job 004 Recepionist
bbb Job 004 Recepionist
bbb Job 104 Recepionist
ccc Job 004 Recepionist
ddd Job 004 Recepionist
相同的代码不同的描述
CATEGORY CODE aaa_DESCR bbb_DESCR ccc_DESCR ddd_DESCR
Dept 002 NULL NULL Pharmacy Labratory
Dept 003 Clerical Laundry IT Accounting
相同的描述不同的代码
CATEGORY DESCR aaa_CODE1 bbb_CODE1 bbb_CODE2 ccc_CODE1 ddd_CODE1
Dept Pharmacy 001 001 NULL 002 NULL
Job Recepionist 004 004 104 004 004
如果不可能有多个列,其中给定位置的同一描述有多个代码,那么可能可以将该位置的所有代码放在一个列中,并用特定字符分隔,如下所示:
CATEGORY DESCR aaa_CODE bbb_CODE ccc_CODE ddd_CODE
Dept Pharmacy 001 001 002 NULL
Job Recepionist 004 004|104 004 004
您需要的第一步是确定需要格式化的行,因此,对于第一个条件,即您希望找到相同代码和类别具有多个描述的位置,我将使用
EXISTS
:
SELECT t.Location, t.Category, t.Code, t.Descr
FROM #T AS t
WHERE EXISTS
( SELECT 1
FROM #T AS t2
WHERE t2.Category = t.Category
AND t2.Code = t.Code
AND t2.Descr != t.Descr
);
这将提供我们需要格式化的行:
Location Category Code Descr
-------------------------------------------
ccc Dept 002 Pharmacy
ddd Dept 002 Labratory
aaa Dept 003 Clerical
bbb Dept 003 Laundry
ccc Dept 003 IT
ddd Dept 003 Accounting
然后,如果每个类别、代码和位置都有一个唯一的Desc
,就像我们在这里所做的那样,您只需在PIVOT
函数中使用任意聚合即可获得所需的格式:
SELECT pvt.Category,
pvt.[aaa],
pvt.[bbb],
pvt.[ccc],
pvt.[ddd]
FROM ( SELECT t.Location, t.Category, t.Code, t.Descr
FROM #T AS t
WHERE EXISTS
( SELECT 1
FROM #T AS t2
WHERE t2.Category = t.Category
AND t2.Code = t.Code
AND t2.Descr != t.Descr
)
) AS t
PIVOT
( MAX(Descr)
FOR Location IN ([aaa], [bbb], [ccc], [ddd])
) AS pvt;
当您可能有多个值时,它会变得更加复杂,因此您不能简单地在PIVOT
中使用MAX
。在这里,您需要使用
下面使用相同的EXISTS
逻辑来查找正确的行,但不只是选择code
而是使用子单元来收集(类别、位置、描述)
的特定组合的所有代码,并将它们合并到一个记录中:
SELECT t.Location,
t.Category,
t.Descr,
Code = STUFF(( SELECT '|' + t2.Code
FROM #T AS t2
WHERE t2.Category = t.Category
AND t2.Descr = t.Descr
AND t2.Location = t.Location
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)'), 1, 1, '')
FROM #T AS t
WHERE EXISTS
( SELECT 1
FROM #T AS t2
WHERE t2.Category = t.Category
AND t2.Descr = t.Descr
AND t2.Code != t.Code
)
GROUP BY t.Location, t.Category, t.Descr;
这使得:
Location Category Descr Code
--------------------------------------------
aaa Dept Pharmacy 001
aaa Job Recepionist 004
bbb Dept Pharmacy 001
bbb Job Recepionist 004|104
ccc Dept Pharmacy 002
ccc Job Recepionist 004
ddd Job Recepionist 004
有了此格式后,您可以再次使用PIVOT
获得所需的输出
SELECT pvt.Category,
pvt.[aaa],
pvt.[bbb],
pvt.[ccc],
pvt.[ddd]
FROM ( SELECT t.Location,
t.Category,
t.Descr,
Code = STUFF(( SELECT '|' + t2.Code
FROM #T AS t2
WHERE t2.Category = t.Category
AND t2.Descr = t.Descr
AND t2.Location = t.Location
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)'), 1, 1, '')
FROM #T AS t
WHERE EXISTS
( SELECT 1
FROM #T AS t2
WHERE t2.Category = t.Category
AND t2.Descr = t.Descr
AND t2.Code != t.Code
)
GROUP BY t.Location, t.Category, t.Descr
) AS t
PIVOT
( MAX(Code)
FOR Location IN ([aaa], [bbb], [ccc], [ddd])
) AS pvt;
为确保完整性,以下是我用于测试的表:
CREATE TABLE #T (Location VARCHAR(3), Category VARCHAR(4), Code CHAR(3), Descr VARCHAR(50));
INSERT INTO #T (Location, Category, Code, Descr)
VALUES
('aaa', 'Dept', '001', 'Pharmacy'),
('bbb', 'Dept', '001', 'Pharmacy'),
('ccc', 'Dept', '002', 'Pharmacy'),
('ddd', 'Dept', '002', 'Labratory'),
('aaa', 'Dept', '003', 'Clerical'),
('bbb', 'Dept', '003', 'Laundry'),
('ccc', 'Dept', '003', 'IT'),
('ddd', 'Dept', '003', 'Accounting'),
('aaa', 'Dept', '004', 'Purchasing'),
('bbb', 'Dept', '004', 'Purchasing'),
('ccc', 'Dept', '004', 'Purchasing'),
('ddd', 'Dept', '004', 'Purchasing'),
('aaa', 'Job', '004', 'Recepionist'),
('bbb', 'Job', '004', 'Recepionist'),
('bbb', 'Job', '104', 'Recepionist'),
('ccc', 'Job', '004', 'Recepionist'),
('ddd', 'Job', '004', 'Recepionist');
你能发布ddl和样本数据吗?sqlfiddle.com将是一个很好的起点。看起来可以通过CASE语句来完成。你熟悉它们的工作原理吗?这太完美了。非常感谢您的提问和解释。有一个问题,如果这是可能的话,很好,如果不是的话,那就是很好,我不想浪费你的时间。在第二种情况下,在给定位置查找类别和描述的代码时,如果在给定位置使用了多个代码,则查询将始终返回代码,即使这些代码仅在一个位置使用,或者相同的代码组在多个位置使用,因此,从某种意义上说,这并没有什么不同。您需要做什么修改才能只显示使用不同代码的位置?非常感谢。