下面是c#中的for循环,它按0和1的顺序返回1的位置,这是我的代码
public string OnesPosition(string statusBits)
{
string onePos = "";
for (int i = 0; i < statusBits.Length; i++)
{
if (statusBits[i] == '1')
{
onePos = onePos + Convert.ToSingle(i + 1) + ",";
}
}
onePos = string.IsNullOrEmpty(onePos ) ? "0," : onePos ;
return onePos;
}
var result = OnesPosition("00000000000101");
这将返回:结果= 12,14
如何在sql查询或使用SQL函数中做到这一点? 使用SQL Server Management Studio v17.9
答案 0 :(得分:4)
另一个选择
示例
Declare @S varchar(50) = '00000000000101'
Select Stuff((Select concat(',',N )
From (
Select Top (len(@S)) N=Row_Number() Over (Order By (Select NULL))
From master..spt_values
) s
Where substring(@S,N,1)='1'
Order By N
For XML Path ('')),1,1,'')
返回
12,14
答案 1 :(得分:1)
循环在SQL Server中不能很好地发挥作用,但这是一种方法。
declare @ones varchar(16) = '00000000100101'
declare @pos int = 1
declare @result varchar(256) = ''
while @pos <= len(@ones)
begin
set @result = @result + case when substring(@ones,@pos,1) = 1 then ',' + cast(@pos as varchar) else '' end
set @pos = @pos + 1
end
select right(@result,len(@result) - 1)
答案 2 :(得分:1)
解决方案:
另一种可能的方法是使用递归CTE(返回每个数字和数字位置)和组连接。
使用STRING_AGG()(来自SQL Server 2017):
DECLARE @ones varchar(16)
SET @ones = '1000000001001011';
WITH Digits AS (
SELECT 1 AS DigitPosition, SUBSTRING(@ones, 1, 1) AS Digit
UNION ALL
SELECT DigitPosition + 1, SUBSTRING(@ones, DigitPosition + 1, 1)
FROM Digits
WHERE DigitPosition < LEN(@ones)
)
SELECT STRING_AGG(DigitPosition, ',')
FROM Digits
WHERE Digit = '1'
使用FOR XML:
DECLARE @ones varchar(16)
SET @ones = '1000000001001011';
WITH Digits AS (
SELECT 1 AS DigitPosition, SUBSTRING(@ones, 1, 1) AS Digit
UNION ALL
SELECT DigitPosition + 1, SUBSTRING(@ones, DigitPosition + 1, 1)
FROM Digits
WHERE DigitPosition < LEN(@ones)
)
SELECT CONVERT(varchar(max), DigitPosition) + ','
FROM Digits
WHERE Digit = '1'
FOR XML PATH('')
输出:
1,10,13,15,16
答案 3 :(得分:0)
我认为使用循环不是一个好主意,但是既然您想要
DECLARE @Str VARCHAR(45) = '000001000000101',
@OutPut VARCHAR(45) = '',
@I INT = 1;
WHILE @I <= LEN(@Str)
BEGIN
IF (SELECT SUBSTRING(@Str, @I, 1)) = '1'
SET @OutPut = @OutPut + (SELECT CAST(@I AS VARCHAR(10))) + ',';
--Convert.ToSingle(i + 1) why +1?
SET @I = @I + 1;
END
SELECT @OutPut;
答案 4 :(得分:0)
使用计数表和直接tsql的另一种方法:
WITH Tally(i) AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS i
FROM (VALUES (0), (0), (0), (0), (0), (0), (0)) a(n)
CROSS JOIN (VALUES (0), (0), (0), (0), (0), (0)) b(n)
)
SELECT bitloc
FROM
(
SELECT SUBSTRING(x.d, i, 1) as bitset, i bitloc
FROM (VALUES ('00000000000101')) x(d)
CROSS JOIN Tally
) sub
WHERE bitset = 1
答案 5 :(得分:0)
这是基于@scsimon响应的函数,它可以正常工作。
CREATE FUNCTION [dbo].[ConvertTo1Positions]
(
@ones AS varchar(16),
@pos AS INT = 1,
@result varchar(256)
) RETURNS VARCHAR(MAX) AS BEGIN
while @pos <= len(@ones)
begin
set @result = @result + iif(substring(@ones,@pos,1) = 1,cast(@pos as char),'')
set @pos = @pos + 1
end
RETURN @result;
END
答案 6 :(得分:0)
或者这个...
DECLARE @string VARCHAR(100) = '00000000000101';
WITH
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)),
cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b),
cte_Tally (n) AS (
SELECT TOP (LEN(@string))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
cte_n2 a CROSS JOIN cte_n2 b
)
SELECT
STRING_AGG(t.n, ',')
FROM
cte_Tally t
WHERE
SUBSTRING(@string, t.n, 1) = '1';