T-SQL에 노드를 연결하는 존재 함수가 있습니까?
다음과 같이 쿼리중인 뷰가 있습니다.
BuildingName PollNumber ------------ ---------- Foo Centre 12 Foo Centre 13 Foo Centre 14 Bar Hall 15 Bar Hall 16 Baz School 17
BuildingNames를 함께 그룹화하고 다음과 같이 PollNumbers 목록을 표시하는 쿼리를 작성해야합니다.
BuildingName PollNumbers ------------ ----------- Foo Centre 12, 13, 14 Bar Hall 15, 16 Baz School 17
T-SQL에서 어떻게 할 수 있습니까? 과잉처럼 보이기 때문에 저장 프로 시저를 작성하는 데 의지하지 않고 정확히 데이터베이스 전문가는 아닙니다. SUM () 또는 AVG ()와 같은 존재하는 함수가 필요한 것 같지만 T-SQL에 하나가 있는지 모르겠습니다. SQL Server 2005를 사용하고 있습니다.
SQL Server 2017 이상 사용 :
STRING_AGG ()
set nocount on;
declare @YourTable table (RowID int, HeaderValue int, ChildValue varchar(5))
insert into @YourTable VALUES (1,1,'CCC')
insert into @YourTable VALUES (2,2,'B<&>B')
insert into @YourTable VALUES (3,2,'AAA')
insert into @YourTable VALUES (4,3,'<br>')
insert into @YourTable VALUES (5,3,'A & Z')
set nocount off
SELECT
t1.HeaderValue
,STUFF(
(SELECT
', ' + t2.ChildValue
FROM @YourTable t2
WHERE t1.HeaderValue=t2.HeaderValue
ORDER BY t2.ChildValue
FOR XML PATH(''), TYPE
).value('.','varchar(max)')
,1,2, ''
) AS ChildValues
FROM @YourTable t1
GROUP BY t1.HeaderValue
SELECT
HeaderValue, STRING_AGG(ChildValue,', ')
FROM @YourTable
GROUP BY HeaderValue
다수 :
HeaderValue
----------- -------------
1 CCC
2 B<&>B, AAA
3 <br>, A & Z
(3 rows affected)
SQL Server 2005 및 2016까지의 경우 다음과 같이 수행해야합니다.
--Concatenation with FOR XML and eleminating control/encoded character expansion "& < >"
set nocount on;
declare @YourTable table (RowID int, HeaderValue int, ChildValue varchar(5))
insert into @YourTable VALUES (1,1,'CCC')
insert into @YourTable VALUES (2,2,'B<&>B')
insert into @YourTable VALUES (3,2,'AAA')
insert into @YourTable VALUES (4,3,'<br>')
insert into @YourTable VALUES (5,3,'A & Z')
set nocount off
SELECT
t1.HeaderValue
,STUFF(
(SELECT
', ' + t2.ChildValue
FROM @YourTable t2
WHERE t1.HeaderValue=t2.HeaderValue
ORDER BY t2.ChildValue
FOR XML PATH(''), TYPE
).value('.','varchar(max)')
,1,2, ''
) AS ChildValues
FROM @YourTable t1
GROUP BY t1.HeaderValue
다수 :
HeaderValue ChildValues
----------- -------------------
1 CCC
2 AAA, B<&>B
3 <br>, A & Z
(3 row(s) affected)
또한 모든 FOR XML PATH
연결이 위의 예제와 같이 XML 특수 문자를 제대로 처리하는 것은 아닙니다 .
Sql Server에는 기본 제공 기능이 없지만 사용자 정의를 작성하여 수행 할 수 있습니다. 이 기사에서는 SQL Server 샘플의 일부로 함수를 언급합니다. http://msdn.microsoft.com/en-us/library/ms182741.aspx
예를 들어 결합에 대한 코드를 포함합니다. 이를 사용하여 Visual Studio에서 데이터베이스 프로젝트를 생성하고 새 SqlAggregate를 추가하고 코드를 아래 샘플로 바꿉니다. 일단 배포되면 데이터베이스와 존재 함수에서 새 어셈블리를 찾아야합니다.Concatenate
using System;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
using Microsoft.SqlServer.Server;
[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined, IsInvariantToNulls = true, IsInvariantToDuplicates = false, IsInvariantToOrder = false, MaxByteSize = 8000, Name = "Concatenate")]
public class Concatenate : IBinarySerialize
{
private StringBuilder _intermediateResult;
internal string IntermediateResult {
get
{
return _intermediateResult.ToString();
}
}
public void Init()
{
_intermediateResult = new StringBuilder();
}
public void Accumulate(SqlString value)
{
if (value.IsNull) return;
_intermediateResult.Append(value.Value);
}
public void Merge(Concatenate other)
{
if (null == other)
return;
_intermediateResult.Append(other._intermediateResult);
}
public SqlString Terminate()
{
var output = string.Empty;
if (_intermediateResult != null && _intermediateResult.Length > 0)
output = _intermediateResult.ToString(0, _intermediateResult.Length - 1);
return new SqlString(output);
}
public void Read(BinaryReader reader)
{
if (reader == null)
throw new ArgumentNullException("reader");
_intermediateResult = new StringBuilder(reader.ReadString());
}
public void Write(BinaryWriter writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
writer.Write(_intermediateResult.ToString());
}
}
이를 사용하는 것입니다.
create table test(
id int identity(1,1) not null
primary key
, class tinyint not null
, name nvarchar(120) not null )
insert into test values
(1, N'This'),
(1, N'is'),
(1, N'just'),
(1, N'a'),
(1, N'test'),
(2, N','),
(3, N'do'),
(3, N'not'),
(3, N'be'),
(3, N'alarmed'),
(3, N','),
(3, N'this'),
(3, N'is'),
(3, N'just'),
(3, N'a'),
(3, N'test')
select dbo.Concatenate(name + ' ')
from test
group by class
drop table test
쿼리의 출력은 다음과 가변합니다.
-- Output
-- ===================
-- This is just a test
-- ,
-- do not be alarmed , this is just a test
클래스와 집계를 여기에서 찾을 수있는 스크립트로 패키지화했습니다 : https://gist.github.com/FilipDeVos/5b7b4addea1812067b09
'ProgramingTip' 카테고리의 다른 글
일반 메서드에서 프로토콜 기본 구현 호출 (0) | 2020.10.27 |
---|---|
Dispatcher.BeginInvoke : 람다를 System.Delegate로 변환 할 수 없습니다. (0) | 2020.10.26 |
"JPEG 파일이 아닙니다 : 0x89 0x50으로 시작"오류가 발생하는 이유 (0) | 2020.10.26 |
Golang 어디에서 문자를 인덱싱하는 방법은 무엇입니까? (0) | 2020.10.26 |
Ruby의 커널 클래스에 assert () 메소드를 추가하는 것이 관용적 인 Ruby입니까? (0) | 2020.10.26 |