Return 单个值取决于可变大小的数据集的内容

Return a single value depending on contents of a variably sized set of data

我正在从数据库中查询用户信息。我特别感兴趣的是从名为 CONTENTS 的字段中获取数据,但前提是给定 USERID 存在匹配的 DESCRIPTION。此外,我不想 return CONTENTS,而是想解析其中的一组。行数 returned 可以是可变的,从 0 到非常大的数量。 CONTENTS 字段将始终是一个字符或没有字符。根据是否在集合中找到某个字符,我将 return 不同的值。不,WHERE 子句在这里没有帮助,因为我只想要一个结果,而不管行数 returned.

我对此有一个有效的查询,但它很大,并且在其中多次复制了 SQL 的类似片段:

IF(
    SELECT COUNT(*)
    FROM TABLE
    WHERE USERID = '123456789'
    AND DESCRIPTION IN ('D1','D2','D3')
    AND CONTENTS NOT IN ('N','',' ')
    ) > 0
    SELECT '*'
ELSE
IF(
    SELECT COUNT(*)
    FROM TABLE
    WHERE USERID = '123456798'
    AND DESCRIPTION IN ('D1','D2','D3')
    ) > 0
    SELECT 'X'
ELSE
    SELECT '_'

如您所见,我将 WHERE 子句复制了两次,我不喜欢这样。理想情况下,我只想看到 WHERE 子句一次。我试图简化它,我明白了,但问题是它 return 不止一行:

SELECT
    CASE
        WHEN COUNT(*) > 0 THEN
            CASE
                WHEN C.CONTENTS = 'N' THEN 'X'
                WHEN C.CONTENTS = ' ' THEN 'X'
                WHEN C.CONTENTS = '' THEN 'X'
                ELSE '*'
            END
        ELSE '_'
    END AS 'RESULT'
FROM TABLE C
WHERE
    USERID = '123456789' AND
    DESCRIPTION IN ('D1','D2','D3')
GROUP BY C.CONTENTS

我相信窗口函数可能对我有帮助,但我很难为这种情况想出一个窗口函数。是否有可能有一个不重复 WHERE 子句的查询可以得到我想要的结果,return 无论行数如何只得到一个结果?

您可以在 COUNT 中使用 CASE WHEN ... END(它不计算 NULL 项),并按 USERID:

分组
SELECT USERID, CASE WHEN STAR > 0 THEN '*' WHEN X > 0 THEN 'X' ELSE '_' END
FROM (
    SELECT USERID, 
        COUNT(CASE WHEN DESCRIPTION IN ('D1','D2','D3') AND CONTENTS NOT IN ('N','',' ') THEN 1 ELSE NULL END) AS STAR,
        COUNT(CASE WHEN DESCRIPTION IN ('D1','D2','D3') THEN 1 ELSE NULL END) AS X
     FROM TABLE
     GROUP BY USERID
     ) AS x
WHERE USERID = '123456789'

我现在这里没有 SQL 服务器,所以我不确定是否可以在没有匿名视图的情况下将它们放在一起。你可以试试看:

SELECT  CASE
            WHEN COUNT(
                CASE WHEN
                        DESCRIPTION IN ('D1','D2','D3')
                    AND CONTENTS NOT IN ('N','',' ') THEN 1
                    ELSE NULL 
                END) > 0 THEN '*'
            WHEN COUNT(
                CASE WHEN
                        DESCRIPTION IN ('D1','D2','D3') THEN 1
                    ELSE NULL
                END) > 0 THEN 'X'
            ELSE '_'
        END
FROM TABLE
WHERE USERID = '123456789'

编辑

要删除重复的 DESCRIPTION IN ('D1'...)(从第一个片段):

SELECT  CASE
            WHEN COUNT_DESCRIPTION > 0 AND COUNT_CONTENTS > 0 THEN '*'
            WHEN COUNT_DESCRIPTION > 0 THEN 'X'
            ELSE '_'
        END
FROM (
    SELECT  USERID, 
        COUNT(CASE WHEN DESCRIPTION IN ('D1','D2','D3') THEN 1 ELSE NULL END) AS COUNT_DESCRIPTION,
        COUNT(CASE WHEN CONTENTS NOT IN ('N','',' ') THEN 1 ELSE NULL END) AS COUNT_CONTENTS
    FROM    TABLE
    GROUP BY USERID
) AS x
WHERE   USERID = '123456789'

但是,如果某些 USERID 的行具有 DESCRIPTION IN ('D1','D2','D3') 而没有 CONTENTS NOT IN ('N','',' ')(即 CONTENTS IN ('N','',' ')),并且 其他,这将不起作用 行有 CONTENTS NOT IN ('N','',' ') 和没有 DESCRIPTION IN ('D1','D2','D3')。对于这样的USERID,最后查询会return'*',但实际上应该return'X'([=18=的行集和[=的行集19=] 不相交)。

编辑 2 (基于以上的新提案,希望能奏效)

SELECT  CASE
            WHEN COUNT(DESCRIPTION_PREDICATE) > 0 AND COUNT(CONTENTS_PREDICATE) > 0 THEN '*'
            WHEN COUNT(CONTENTS_PREDICATE) > 0 THEN 'X'
            ELSE '_'
        END
FROM (
    SELECT  USERID, 
        CASE WHEN DESCRIPTION IN ('D1','D2','D3') THEN 1 ELSE NULL END AS DESCRIPTION_PREDICATE,
        CASE WHEN CONTENTS NOT IN ('N','',' ') THEN 1 ELSE NULL END) AS CONTENTS_PREDICATE
    FROM    TABLE
) AS x
WHERE   USERID = '123456789'
GROUP BY USERID

在 rslemos 之前发布的内容的基础上,我找到了一个符合我要求的解决方案,并且仍然易于阅读和理解。

SELECT
    CASE
        WHEN COUNT(
            CASE
                WHEN CONTENTS NOT IN ('N','',' ') THEN 1
                ELSE NULL 
            END) > 0 THEN '*'
        WHEN COUNT(*) > 0 THEN 'X'
        ELSE '_'
    END AS 'RESULT'
FROM TABLE
WHERE USERID = '123456789'
AND DESCRIPTION IN ('D1','D2','D3')

由于我使用的是 COUNT(*),所以我对这个还是有点不确定,但到目前为止,它已经通过了我需要它通过的测试。