Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 查询以根据特定列中的值相互比较表中的值,并仅显示忽略空值的差异_Sql_Sql Server - Fatal编程技术网

Sql 查询以根据特定列中的值相互比较表中的值,并仅显示忽略空值的差异

Sql 查询以根据特定列中的值相互比较表中的值,并仅显示忽略空值的差异,sql,sql-server,Sql,Sql Server,我有一个数据表,显示不同位置使用的不同代码和描述。我需要将这些位置合并为一个。在这样做之前,我需要能够清楚地看到两组数据,一组是用于给定位置的给定类别中的代码的不同描述,另一组是用于给定位置的给定类别中的描述的不同代码,这样我才能使数据一致。虽然给定的代码在每个位置的每个类别中只有一个描述,但给定的描述在每个位置的每个类别中可以有多个代码。我只关心不同地点使用不同代码和类别的情况。出于这些目的,在一个或多个位置相同但在其他位置未使用的代码或描述没有区别 我需要能够运行一个查询,为给定的类别和代码

我有一个数据表,显示不同位置使用的不同代码和描述。我需要将这些位置合并为一个。在这样做之前,我需要能够清楚地看到两组数据,一组是用于给定位置的给定类别中的代码的不同描述,另一组是用于给定位置的给定类别中的描述的不同代码,这样我才能使数据一致。虽然给定的代码在每个位置的每个类别中只有一个描述,但给定的描述在每个位置的每个类别中可以有多个代码。我只关心不同地点使用不同代码和类别的情况。出于这些目的,在一个或多个位置相同但在其他位置未使用的代码或描述没有区别

我需要能够运行一个查询,为给定的类别和代码显示按位置列出的所有描述,包括未使用该代码的空值,所有位置的描述都不相同。同样,如果代码除了null之外没有其他差异,那么它不应该在列表中

我需要能够运行另一个查询,该查询将按位置显示给定类别和描述的所有代码,包括未使用该描述的空代码,所有位置的代码不相同,请记住每个位置可能有多个代码。同样如上所述,如果给定类别和描述的代码相同,但并非在所有位置都使用,则不应返回该代码

因此,如果我的表有:

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语句来完成。你熟悉它们的工作原理吗?这太完美了。非常感谢您的提问和解释。有一个问题,如果这是可能的话,很好,如果不是的话,那就是很好,我不想浪费你的时间。在第二种情况下,在给定位置查找类别和描述的代码时,如果在给定位置使用了多个代码,则查询将始终返回代码,即使这些代码仅在一个位置使用,或者相同的代码组在多个位置使用,因此,从某种意义上说,这并没有什么不同。您需要做什么修改才能只显示使用不同代码的位置?非常感谢。