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.
- 如果集合中有数据:
- 如果数据包含
N
、space 以外的字符或空白,return *
- 其他: return
X
- 其他: return
_
我对此有一个有效的查询,但它很大,并且在其中多次复制了 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(*)
,所以我对这个还是有点不确定,但到目前为止,它已经通过了我需要它通过的测试。
我正在从数据库中查询用户信息。我特别感兴趣的是从名为 CONTENTS
的字段中获取数据,但前提是给定 USERID
存在匹配的 DESCRIPTION
。此外,我不想 return CONTENTS
,而是想解析其中的一组。行数 returned 可以是可变的,从 0 到非常大的数量。 CONTENTS
字段将始终是一个字符或没有字符。根据是否在集合中找到某个字符,我将 return 不同的值。不,WHERE
子句在这里没有帮助,因为我只想要一个结果,而不管行数 returned.
- 如果集合中有数据:
- 如果数据包含
N
、space 以外的字符或空白,return*
- 其他: return
X
- 如果数据包含
- 其他: return
_
我对此有一个有效的查询,但它很大,并且在其中多次复制了 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(*)
,所以我对这个还是有点不确定,但到目前为止,它已经通过了我需要它通过的测试。