只有两个对象 + 休息计数
Only two objects + rest the count
我想显示以下字符串:
苹果、香蕉、腰果、甜甜圈、大象、鱼
转换成这种格式:
苹果、香蕉 + 其他 4 个
我只想显示前两个对象,然后再计数!
正如其他人所说,这不是 SQL 服务器的工作,而是您的表示层。根据您的预期结果,我 假设 您的逗号表示您在数据库中存储分隔数据;一个致命的缺陷。如果您规范化您的设计,您可能很容易在您的应用程序层中实现这一点。
由于您使用的是非规范化数据,因此您需要先对其进行规范化,然后再重新聚合。我使用任意 TOP
(每次 运行 查询时行可能不同),因为序号参数仅(当前)在 Azure SQL 数据库中可用;希望序数参数将在 SQL Server 2022 中。
无论如何,这 有效 ,但再次修正您的设计,并在应用程序层执行此操作。如果您没有使用 SQL Server 2017,那么这是必须的,不是一个非常强烈的建议。
DECLARE @Values int = 2; --parameterised, but you could hard code
WITH Split AS(
SELECT SS.[value],
COUNT(*) OVER () AS [Rows]
FROM (VALUES('Apple,Banana,Cashew,Doughnut,Elephant,Fish'))V(YourDenormalisedData)
CROSS APPLY STRING_SPLIT(V.YourDenormalisedData,',') SS),
ArbitraryTop AS(
SELECT TOP (@Values)
value,
[Rows]
FROM Split)
SELECT STRING_AGG(value,', ') +
CASE WHEN MAX([Rows]) > @Values THEN CONCAT(' + ',MAX([Rows])-@Values,' others') ELSE '' END
FROM ArbitraryTop;
正如其他人所说,这不是 SQL 服务器的工作,而是您的表示层
如果你必须在sql中完成,那么也许你可以这样做。
我确实假设您在多行中有这些值,并且需要通过一些分组将它们连接起来,如果没有,那么请在您的问题中更清楚地说明
select o.id,
( select top 2 string_agg(o2.name, ', ')
from ( select top 2 o2.name,
o2.id
from object o2
where o2.id = o.id
) o2
where o2.id = o.id
) + ' and ' + convert(varchar(50), count(o.name) - 2) + ' others'
from object o
group by o.id
看看这个 DBFiddle here 看看它是否有效
结果是这样的
id
(No column name)
1
Apple, Banana and 4 others
2
Peer, Catfish and 0 others
3
Dog, Whale and 1 others
如果您不想显示 'and x others' 您可以像这样更改查询
select o.id,
( select top 2 string_agg(o2.name, ', ')
from ( select top 2 o2.name, o2.id
from object o2
where o2.id = o.id
) o2
where o2.id = o.id
) + case when count(o.name) > 2 then ' and ' + convert(varchar(50), count(o.name) - 2) + ' others'
else ''
end
from object o
group by o.id
id
(No column name)
1
Apple, Banana and 4 others
2
Peer, Catfish
3
Dog, Whale and 1 others
编辑 sql 服务器不支持 string_agg
如果您有不支持 string_agg
函数的旧版本 sql 服务器,您可以使用 XML PATH
连接值和 stuff
删除多余的 ,
select o.id,
stuff(( select top 2 ', ' + o2.name
from ( select top 2 o2.name,
o2.id
from object o2
where o2.id = o.id
) o2
where o2.id = o.id
for XML PATH('')
), 1, 2, ''
) + case when count(o.name) > 2 then ' and ' + convert(varchar(50), count(o.name) - 2) + ' others'
else ''
end
from object o
group by o.id
结果还是一样
这个任务可以用cursor, by dividing the line by the delimenter using function split_string的力量解决。
--@string - our input string
DECLARE @string NVARCHAR(MAX) = 'Apple,Banana,Cashew,Doughnut,Elephant,Fish';
--@count - the number of words in @string
DECLARE @count INT = 0;
--@countrestwords - count of rest words
DECLARE @countrestwords INT = 0;
--@resultstring - result string
DECLARE @resultstring NVARCHAR(MAX) = '';
DECLARE stringcursor CURSOR FOR
SELECT
VALUE
FROM string_split(@string,',')
OPEN stringcursor
FETCH FROM stringcursor INTO @string
WHILE @@FETCH_STATUS = 0
BEGIN
IF @count = 0
BEGIN
SET @resultstring = @string;
END
ELSE IF @count = 1
BEGIN
SET @resultstring = @resultstring +',' +@string ;
END
ELSE
BEGIN
SET @resultstring = @resultstring;
SET @countrestwords = @countrestwords + 1;
--SELECT @countrestwords
END
SET @count = @count + 1;
FETCH NEXT FROM stringcursor INTO @string
END
CLOSE stringcursor
DEALLOCATE stringcursor
SELECT @resultstring + ' + ' + CONVERT(NVARCHAR(MAX),@countrestwords)+' others' ;
GO
这是我创建的,它对我有用。但是,它需要优化。
Declare @test_count int = 0, @test1_pos int = 0, @test2_pos int = 0, @test_product varchar(500), @test_product2 varchar(500),@tests varchar(500);
--select distinct top 1 product,CHARINDEX(',',product,1), CHARINDEX(',',product,CHARINDEX(',',product,1)+1) from ReportDB..wo_result_detail where CustomerId=@LAB_CODE
select distinct top 1 @test_product = product,@test1_pos=CHARINDEX(',',product,1), @test1_pos = CHARINDEX(',',product,CHARINDEX(',',product,1)+1)
from [table name] where [condition]
select distinct top 1 @test_product = product, @test_product2 =
case when @test1_pos <> 0 or @test2_pos <> 0 then (
select top 1 left(product,CHARINDEX(',',product,CHARINDEX(',',product,1)+1)-1) from [table name] where [condition]
)
else @test_product
end from [table name] where [condition]
select @test_count = (len(replace(@test_product,',',', '))+1) - len(@test_product)
select top 1 @tests= case when @test_count> 2 then concat ( @test_product2 ,' + ',@test_count-2 ,' Others')
else @test_product end
我想显示以下字符串:
苹果、香蕉、腰果、甜甜圈、大象、鱼
转换成这种格式:
苹果、香蕉 + 其他 4 个
我只想显示前两个对象,然后再计数!
正如其他人所说,这不是 SQL 服务器的工作,而是您的表示层。根据您的预期结果,我 假设 您的逗号表示您在数据库中存储分隔数据;一个致命的缺陷。如果您规范化您的设计,您可能很容易在您的应用程序层中实现这一点。
由于您使用的是非规范化数据,因此您需要先对其进行规范化,然后再重新聚合。我使用任意 TOP
(每次 运行 查询时行可能不同),因为序号参数仅(当前)在 Azure SQL 数据库中可用;希望序数参数将在 SQL Server 2022 中。
无论如何,这 有效 ,但再次修正您的设计,并在应用程序层执行此操作。如果您没有使用 SQL Server 2017,那么这是必须的,不是一个非常强烈的建议。
DECLARE @Values int = 2; --parameterised, but you could hard code
WITH Split AS(
SELECT SS.[value],
COUNT(*) OVER () AS [Rows]
FROM (VALUES('Apple,Banana,Cashew,Doughnut,Elephant,Fish'))V(YourDenormalisedData)
CROSS APPLY STRING_SPLIT(V.YourDenormalisedData,',') SS),
ArbitraryTop AS(
SELECT TOP (@Values)
value,
[Rows]
FROM Split)
SELECT STRING_AGG(value,', ') +
CASE WHEN MAX([Rows]) > @Values THEN CONCAT(' + ',MAX([Rows])-@Values,' others') ELSE '' END
FROM ArbitraryTop;
正如其他人所说,这不是 SQL 服务器的工作,而是您的表示层
如果你必须在sql中完成,那么也许你可以这样做。
我确实假设您在多行中有这些值,并且需要通过一些分组将它们连接起来,如果没有,那么请在您的问题中更清楚地说明
select o.id,
( select top 2 string_agg(o2.name, ', ')
from ( select top 2 o2.name,
o2.id
from object o2
where o2.id = o.id
) o2
where o2.id = o.id
) + ' and ' + convert(varchar(50), count(o.name) - 2) + ' others'
from object o
group by o.id
看看这个 DBFiddle here 看看它是否有效
结果是这样的
id | (No column name) |
---|---|
1 | Apple, Banana and 4 others |
2 | Peer, Catfish and 0 others |
3 | Dog, Whale and 1 others |
如果您不想显示 'and x others' 您可以像这样更改查询
select o.id,
( select top 2 string_agg(o2.name, ', ')
from ( select top 2 o2.name, o2.id
from object o2
where o2.id = o.id
) o2
where o2.id = o.id
) + case when count(o.name) > 2 then ' and ' + convert(varchar(50), count(o.name) - 2) + ' others'
else ''
end
from object o
group by o.id
id | (No column name) |
---|---|
1 | Apple, Banana and 4 others |
2 | Peer, Catfish |
3 | Dog, Whale and 1 others |
编辑 sql 服务器不支持 string_agg
如果您有不支持 string_agg
函数的旧版本 sql 服务器,您可以使用 XML PATH
连接值和 stuff
删除多余的 ,
select o.id,
stuff(( select top 2 ', ' + o2.name
from ( select top 2 o2.name,
o2.id
from object o2
where o2.id = o.id
) o2
where o2.id = o.id
for XML PATH('')
), 1, 2, ''
) + case when count(o.name) > 2 then ' and ' + convert(varchar(50), count(o.name) - 2) + ' others'
else ''
end
from object o
group by o.id
结果还是一样
这个任务可以用cursor, by dividing the line by the delimenter using function split_string的力量解决。
--@string - our input string
DECLARE @string NVARCHAR(MAX) = 'Apple,Banana,Cashew,Doughnut,Elephant,Fish';
--@count - the number of words in @string
DECLARE @count INT = 0;
--@countrestwords - count of rest words
DECLARE @countrestwords INT = 0;
--@resultstring - result string
DECLARE @resultstring NVARCHAR(MAX) = '';
DECLARE stringcursor CURSOR FOR
SELECT
VALUE
FROM string_split(@string,',')
OPEN stringcursor
FETCH FROM stringcursor INTO @string
WHILE @@FETCH_STATUS = 0
BEGIN
IF @count = 0
BEGIN
SET @resultstring = @string;
END
ELSE IF @count = 1
BEGIN
SET @resultstring = @resultstring +',' +@string ;
END
ELSE
BEGIN
SET @resultstring = @resultstring;
SET @countrestwords = @countrestwords + 1;
--SELECT @countrestwords
END
SET @count = @count + 1;
FETCH NEXT FROM stringcursor INTO @string
END
CLOSE stringcursor
DEALLOCATE stringcursor
SELECT @resultstring + ' + ' + CONVERT(NVARCHAR(MAX),@countrestwords)+' others' ;
GO
这是我创建的,它对我有用。但是,它需要优化。
Declare @test_count int = 0, @test1_pos int = 0, @test2_pos int = 0, @test_product varchar(500), @test_product2 varchar(500),@tests varchar(500);
--select distinct top 1 product,CHARINDEX(',',product,1), CHARINDEX(',',product,CHARINDEX(',',product,1)+1) from ReportDB..wo_result_detail where CustomerId=@LAB_CODE
select distinct top 1 @test_product = product,@test1_pos=CHARINDEX(',',product,1), @test1_pos = CHARINDEX(',',product,CHARINDEX(',',product,1)+1)
from [table name] where [condition]
select distinct top 1 @test_product = product, @test_product2 =
case when @test1_pos <> 0 or @test2_pos <> 0 then (
select top 1 left(product,CHARINDEX(',',product,CHARINDEX(',',product,1)+1)-1) from [table name] where [condition]
)
else @test_product
end from [table name] where [condition]
select @test_count = (len(replace(@test_product,',',', '))+1) - len(@test_product)
select top 1 @tests= case when @test_count> 2 then concat ( @test_product2 ,' + ',@test_count-2 ,' Others')
else @test_product end