我正在查询数据库中的用户信息。我特别感兴趣的是从名为CONTENTS
的字段中获取数据,但仅限于给定DESCRIPTION
的匹配USERID
。另外,我不想返回CONTENTS
,而是想要解析它们中的一组。返回的行数可以是可变的,从0到非常大的量。 CONTENTS
字段始终为一个字符或无字符。根据是否在集合中找到某个字符,我将返回不同的值。不,WHERE
子句在这里没有帮助,因为我只想要一个结果,无论返回的行数是多少。
N
,空格或空白以外的字符,请返回*
X
_
我有一个有效的查询,但它很大并且在其中多次复制类似的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
条款。我试图简化这个,我得到了这个,但问题是它返回了多行:
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
子句的查询可以得到我想要的结果,只返回一个结果而不管行数?
答案 0 :(得分:1)
您可以使用CASE WHEN ... END
内的COUNT
(它不会计算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 Server,所以我不确定它是否可以在没有匿名视图的情况下完成。你可以尝试一下:
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,最后一个查询将返回' *',但实际上应该返回' X' (DESCRIPTION IN ('D1','D2','D3')
的行集和CONTENTS NOT IN ('N','',' ')
的行集是不相交的。)
编辑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
答案 1 :(得分:0)
基于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(*)
,所以我仍然对这个问题有点不确定,但到目前为止,我已经通过了我需要通过的测试。