我有一个包含Tags
列的表格,其中包含以下内容:'server, network, location1'
...
我需要查找项目' storage
'存在
和
存在任何这些位置的地方('location1', location2, location3')
和
没有其他项目存在的情况(即只有' storage
'和location
或者只有' storage
')。
我使用函数将字符串拆分为项目,因此下面代码的select语句使用整个字符串的标签和项目的项目将对我有所帮助。
SELECT cardid, item, tags, count(1) as Total
, result =
case when lower(item) = 'storage' and
lower(item) in 'location1, location2, location3'
then 'yes'
else 'no'
end
FROM myTable
CROSS APPLY dbo.fn_SplitString(Tags, ',')
GROUP BY cardid, item, tags
order by item desc
这是我使用的功能:
CREATE FUNCTION [dbo].[fn_SplitString]
(
@String VARCHAR(8000),
@Delimiter VARCHAR(255)
)
RETURNS
@Results TABLE
(
ID INT IDENTITY(1, 1),
Item VARCHAR(8000)
)
AS
BEGIN
INSERT INTO @Results (Item)
SELECT SUBSTRING(@String+@Delimiter, Number,
CHARINDEX(@Delimiter, @String+@Delimiter, Number) - Number)
FROM Numbers
WHERE Number <= LEN(REPLACE(@String,' ','|'))
AND SUBSTRING(@Delimiter + @String,
Number,
LEN(REPLACE(@delimiter,' ','|'))) = @Delimiter
ORDER BY Number RETURN
END
答案 0 :(得分:0)
&#34;查找所有记录......&#34;您的查询应更改为:
SELECT MT.cardid, MT.tags, count(1) as Total
FROM myTable AS MT
CROSS APPLY dbo.fn_SplitString(Tags, ',') AS TagList
GROUP BY MT.cardid, MT.tags
HAVING COUNT( * ) =
COUNT( CASE WHEN TagList.Item IN( 'location1', 'location2', 'location3' ) THEN 1 ELSE NULL END )
+ COUNT( CASE WHEN TagList.Item = 'storage' THEN 1 ELSE NULL END )
AND COUNT( CASE WHEN TagList.Item = 'storage' THEN 1 ELSE NULL END ) >= 1
ORDER BY MT.cardid DESC
上述查询正在使用&#34;条件聚合&#34;。我添加了HAVING
子句,其中所有标签的每个组COUNT
都与&#34;位置&#34;的总和进行比较。标签COUNT
和&#34;存储&#34;标记COUNT
。下一个条件检查&#34;存储&#34;的COUNT
。大于或等于1(如果只需要1个存储元素而不是将其更改为= 1
)
注意:我假设您的dbo.fn_SplitString函数返回一个表格,其中包含名为&#34; Item&#34;。的列
注意2:请注意我已为该函数指定了别名(&#34; AS TagList&#34;)。
如果您希望查询返回所有行,只需指示行是否与您的标记条件匹配(例如您提供的示例查询),请将所有HAVING
条件移至CASE
语句并删除HAVING
SELECT MT.cardid, MT.tags, COUNT(*) as Total
, result =
CASE
WHEN COUNT( * ) =
COUNT( CASE WHEN TagList.Value IN( 'location1', 'location2', 'location3' ) THEN 1 ELSE NULL END )
+ COUNT( CASE WHEN TagList.Value = 'storage' THEN 1 ELSE NULL END )
AND COUNT( CASE WHEN TagList.Item = 'storage' THEN 1 ELSE NULL END ) >= 1
THEN 'yes'
ELSE 'no'
END
FROM myTable AS MT
CROSS APPLY dbo.fn_SplitString(Tags, ',') AS TagList
GROUP BY MT.cardid, MT.tags
ORDER BY MT.cardid DESC
以下是一个工作示例:
DECLARE @Sample TABLE( GroupID INT, Tag VARCHAR( 20 ))
INSERT INTO @Sample( GroupID, Tag )
VALUES
( 1, 'location1' ),( 1, 'location2' ), ( 1, 'storage' ),
( 2, 'location1' ),( 2, 'location2' ), ( 2, 'something else' ),
( 3, 'storage' )
SELECT GroupID
FROM @Sample AS TagList
GROUP BY GroupID
HAVING COUNT( * ) =
COUNT( CASE WHEN TagList.Tag IN( 'location1', 'location2', 'location3' ) THEN 1 ELSE NULL END )
+ COUNT( CASE WHEN TagList.Tag = 'storage' THEN 1 ELSE NULL END )
AND COUNT( CASE WHEN TagList.Tag = 'storage' THEN 1 ELSE NULL END ) >= 1
将来请提供如上所示的样本表。
更新(回答您的意见):
请注意,下面的函数是一个表值函数,它返回一个包含一列的表:@Results TABLE( Value VARCHAR( MAX ))
。列的名称是&#34;值&#34; (在您的情况下,它可能是一个不同的名称)。因此,在查询中访问此函数返回的数据时,请指定此列的名称(在我的情况下,它是&#34;值&#34;)。
CREATE FUNCTION dbo.fn_SplitString
(
@Source VARCHAR( MAX ),
@Delimiter VARCHAR( 100 )
)
RETURNS @Results TABLE( Value VARCHAR( MAX ))
AS
BEGIN
-- The main body of code has been excluded for brevity
END
链接到包含解释的类似问题:
T-SQL SUM All with a Conditional COUNT
Create a view with totals from multiple columns
SQL Server - conditional aggregation with correlation