如果我的查询输出是英格兰,美国,印度。
是否可以显示查询结果,例如英格兰,美国和印度
这是我的问题:
Select stuff( ( Select Distinct ',' + Country as[text()]
from tbl_Country
where OrderNo in (Select Max(OrderNo) from Tbl_Literature where ID='AB123'
Group By OrderNo) for XML path('') ),1,1,'')as Result
from dbo.Tbl_Master as TP
where
TP.OrderNo IN (select MAX(order No) from dbo.Tbl_Master where TP.ID = 'AB123')
答案 0 :(得分:2)
假设您指的是为了弥补SqlServer缺少GROUP_CONCAT
所做的字符串聚合黑客攻击,您可以在此处使用此ingenious hack:
WITH myStuffedCte AS
(SELECT
STUFF((
SELECT ',' + Name
FROM Country
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS SomeCol
)
SELECT ISNULL(reverse(replace(STUFF(reverse(SomeCol),
charindex(',',reverse(SomeCol)),0,'#'),'#,',' dna ')),
SomeCol)
FROM myStuffedCte;
使用GROUPING
条件
为了以STUFF
方式使用GROUP BY
,您可以根据具有WHERE
子句的外部查询行手动过滤内部STUFF子查询。
WITH myStuffedCte AS
(
SELECT p.FirstName, p.LastName,
STUFF((
SELECT ',' + c.Name
FROM Country c
INNER JOIN PersonCountryVisits pcv
ON pcv.CountryId = c.CountryId
WHERE pcv.PersonId = p.PersonID -- Manual Filter step
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS SomeCol
FROM Person p
)
SELECT FirstName, LastName,
ISNULL(reverse(replace(STUFF(reverse(SomeCol),
charindex(',',reverse(SomeCol)),0,'#'),'#,',' dna ')),
SomeCol) AS CountriesVisited
FROM myStuffedCte;
Updated Sql Fiddle example here
SqlClr替代Stuff
,IFF你可以在你的SqlServer上使用SqlClr:
如果您有权访问启用了Sql-Clr的SqlServer,则可以放弃这两个hacks,而是将STUFF / FOR XML
替换为GROUP_CONCAT simulation of SqlUserDefinedAggregate
like this one,同时执行最后一个逗号替换为SqlFunction
UDF,如下所示:
[SqlFunction]
public static SqlString ReplaceLast(SqlString source, SqlString find, SqlString replace,
int countFromRight)
{
var splits = source.Value
.Split(new[] {find.Value}, StringSplitOptions.None);
var replacePoint = splits.Length - countFromRight;
return (replacePoint > 0)
? new SqlString(
string.Join(replace.Value,
new[] { string.Join(find.Value, splits.Take(replacePoint)) }
.Union(splits.Skip(replacePoint))))
: source;
}
在这种情况下,样本查询变得更加可口:
SELECT FirstName, LastName,
dbo.ReplaceLast(dbo.GROUP_CONCAT(c.Name, ','), ',', ' and ', 1)
FROM Person p
INNER JOIN PersonCountryVisits pcv
ON pcv.PersonId = p.PersonID
INNER JOIN Country c
ON pcv.CountryId = c.CountryId
GROUP BY FirstName, LastName;
我已经提出了一个Gist on GitHub,它提供了创建GROUP_CONCAT
和ReplaceLast
SqlClr函数的所有重要位。 (SqlFiddle不可用 - 没有SQLClr ......)
答案 1 :(得分:2)
正如你提到的stuff命令,我假设你使用FOR XML PATH('')
连接你的项目,STUFF
删除第一个分隔符,例如。
SELECT STUFF(( SELECT ', ' + Country
FROM InnerTable AS i
WHERE i.ID = o.ID
ORDER BY Country
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
FROM OuterTable AS o;
如果是这种情况,那么您可以使用ROW_NUMBER()
来标识最后一行(通过使用子查询的反向排序),并将AND
放在那里:
SELECT STUFF(( SELECT ', ' + CASE WHEN ROW_NUMBER() OVER(ORDER BY Country DESC) = 1
THEN 'and '
ELSE ''
END + Country
FROM InnerTable AS i
WHERE i.ID = o.ID
ORDER BY Country ASC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
FROM OuterTable AS o;
n.b。上面会产生一个字符串serial comma(例如"英格兰,美国和印度"),但它不需要太多操作来改变它。
简单示例
SELECT STUFF(( SELECT ', ' + CASE WHEN ROW_NUMBER() OVER(ORDER BY Country DESC) = 1
THEN 'and '
ELSE ''
END + Country
FROM (VALUES ('America'), ('England'), ('India')) AS i (Country)
ORDER BY Country ASC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '');
答案 2 :(得分:0)
试试这个:
Declare @String varchar(100)
set @String = 'England, America, India'
SELECT reverse(replace(STUFF(reverse(@String),
charindex(',',reverse(@String)),0,'#'),'#,',' dna '))
答案 3 :(得分:0)
使用SUBSTRING()
。有关更多String
功能
DECLARE @s AS VARCHAR(100)
SET @s = 'England, America, India'
SELECT SUBSTRING(@s, 0, LEN(@s) - CHARINDEX(',', REVERSE(@s)) + 1 )
+ ' and'
+ SUBSTRING(@s, LEN(@s) - CHARINDEX(',', REVERSE(@s)) + 2, len(@s))