联接列SQL查询
我有三张桌子: 例如,以下是数据库中的数据: 是否可以编写提供如下结构的网格的查询? 使用简单联接编写查询时,结果如下所示:联接列SQL查询,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有三张桌子: 例如,以下是数据库中的数据: 是否可以编写提供如下结构的网格的查询? 使用简单联接编写查询时,结果如下所示: 在Mysql中,有一个函数组_CONCAT,它将为您执行此操作。AFAIK MSSQL没有类似的功能,但这篇博客文章可能会让您更接近您的目标:您正在寻找的是字符串聚合。T-SQL不是本机实现的,例如,其他数据库都有string_agg。但你可以模拟它 请尝试查找,例如: 或者,对于完成者: 如果在最后一个链接中搜索SQL Server,有三种不同的方法 select s
在Mysql中,有一个函数组_CONCAT,它将为您执行此操作。AFAIK MSSQL没有类似的功能,但这篇博客文章可能会让您更接近您的目标:您正在寻找的是字符串聚合。T-SQL不是本机实现的,例如,其他数据库都有string_agg。但你可以模拟它 请尝试查找,例如: 或者,对于完成者: 如果在最后一个链接中搜索SQL Server,有三种不同的方法
select stuff((select distinct ','+ numbers from testtable for xml path('')),1,1,'')
请尝试此代码谢谢您确认.NET将使用此代码 我问的原因是,我认为数据库不是转换数据的最佳场所。并不是说您永远不应该这样做,而是说最好使用数据库来实现它擅长的功能:存储和检索数据,并在消费代码中进行转换。这是一个可以尝试并遵循的一般原则—它以更原始的格式保留数据,因此以后更可能被其他流程重用和使用 本质上,我认为问题在于你想: 按联系人和联系人类型分组, 然后转置并连接多行电话号码。 我不确定调用数据库的.NET代码是什么样子的,但您可以使用DataTable执行以下操作,例如,假设您有联系人类型:
我手头没有IDE来测试,所以把它当作粗略的代码。不过,您可以从中获得原理。您可以使用CTE收集数据,同时将电话号码旋转到逗号分隔的列表中。它可能效率不高,但却是一个方便的技巧 以下内容在AdventureWorks2008R2上运行,不过您需要在Person.PersonPhone表中填充一些额外数据,以便为单个Person/number类型创建多个电话号码
; with PersonsWithTelephoneNumbersCTE (
BusinessEntityId, FirstName, MiddleName, LastName,
PhoneNumberTypeId, PhoneNumber, PhoneNumbers, Elements )
as (
-- Base case: Just the person identifications with all possible phone types.
select BusinessEntityID, FirstName, MiddleName, LastName, PhoneNumberTypeId,
cast( '' as NVarChar(25) ), cast( '' as VarChar(MAX) ), 0
from Person.Person as PP cross join
Person.PhoneNumberType as PNT
union all
-- Add a telephone number.
select CTE.BusinessEntityId, CTE.FirstName, CTE.MiddleName, CTE.LastName,
PNT.PhoneNumberTypeID, PN.PhoneNumber,
cast( CTE.PhoneNumbers + ', ' + PN.PhoneNumber as VarChar(MAX) ), CTE.Elements + 1
from PersonsWithTelephoneNumbersCTE as CTE inner join
Person.Person as PP on PP.BusinessEntityID = CTE.BusinessEntityId inner join
Person.PhoneNumberType as PNT on PNT.PhoneNumberTypeID = CTE.PhoneNumberTypeId inner join
Person.PersonPhone as PN on PN.BusinessEntityID = CTE.BusinessEntityId and PN.PhoneNumberTypeID = PNT.PhoneNumberTypeID
where PN.PhoneNumber > CTE.PhoneNumber
)
-- Get the person and the longest list of phone numbers for each person/phone type.
select LastName, FirstName, MiddleName,
(select Name from Person.PhoneNumberType where PhoneNumberTypeID = Edna.PhoneNumberTypeID ) as PhoneNumberType,
substring( PhoneNumbers, 3, len( PhoneNumbers ) - 2 ) as PhoneNumbers from (
select BusinessEntityID, FirstName, MiddleName, LastName, PhoneNumberTypeId, PhoneNumbers,
rank() over ( partition by BusinessEntityId, PhoneNumberTypeId order by Elements desc ) as Ranking
from PersonsWithTelephoneNumbersCTE
) as Edna
where Ranking = 1 and PhoneNumbers <> ''
order by LastName, FirstName, MiddleName, PhoneNumberType
根据Aaron的回答,尝试这个查询。它应该以您要查找的表单返回一个结果集
SELECT DISTINCT
c.ContactName
,pt.TypeTitle
,(SELECT pn2.PhoneNO + ', '
FROM dbo.PhoneNumber AS pn2
WHERE pn.PhoneType = pn2.PhoneType
AND pn.ContactID = pn2.ContactID
FOR XML PATH ('')
) AS Numbers
FROM dbo.Contact AS c
INNER JOIN dbo.PhoneNumber AS pn
ON c.ContactID = pn.ContactID
INNER JOIN dbo.PhoneType AS pt
ON pn.PhoneType = pt.PhoneTypeID
我不明白你在问什么。你能重新措辞吗?离题:你所问的是可能的。首先,这是由.NET应用程序使用的吗?我这样问是因为这样做会更干净LINQ@Neil芬威克是的,没错。你能解释一下我是如何使用LINQ来做这件事的吗?可能是+1的副本这是正确的地方。如果我能提供C代码,我会+2。
; with PersonsWithTelephoneNumbersCTE (
BusinessEntityId, FirstName, MiddleName, LastName,
PhoneNumberTypeId, PhoneNumber, PhoneNumbers, Elements )
as (
-- Base case: Just the person identifications with all possible phone types.
select BusinessEntityID, FirstName, MiddleName, LastName, PhoneNumberTypeId,
cast( '' as NVarChar(25) ), cast( '' as VarChar(MAX) ), 0
from Person.Person as PP cross join
Person.PhoneNumberType as PNT
union all
-- Add a telephone number.
select CTE.BusinessEntityId, CTE.FirstName, CTE.MiddleName, CTE.LastName,
PNT.PhoneNumberTypeID, PN.PhoneNumber,
cast( CTE.PhoneNumbers + ', ' + PN.PhoneNumber as VarChar(MAX) ), CTE.Elements + 1
from PersonsWithTelephoneNumbersCTE as CTE inner join
Person.Person as PP on PP.BusinessEntityID = CTE.BusinessEntityId inner join
Person.PhoneNumberType as PNT on PNT.PhoneNumberTypeID = CTE.PhoneNumberTypeId inner join
Person.PersonPhone as PN on PN.BusinessEntityID = CTE.BusinessEntityId and PN.PhoneNumberTypeID = PNT.PhoneNumberTypeID
where PN.PhoneNumber > CTE.PhoneNumber
)
-- Get the person and the longest list of phone numbers for each person/phone type.
select LastName, FirstName, MiddleName,
(select Name from Person.PhoneNumberType where PhoneNumberTypeID = Edna.PhoneNumberTypeID ) as PhoneNumberType,
substring( PhoneNumbers, 3, len( PhoneNumbers ) - 2 ) as PhoneNumbers from (
select BusinessEntityID, FirstName, MiddleName, LastName, PhoneNumberTypeId, PhoneNumbers,
rank() over ( partition by BusinessEntityId, PhoneNumberTypeId order by Elements desc ) as Ranking
from PersonsWithTelephoneNumbersCTE
) as Edna
where Ranking = 1 and PhoneNumbers <> ''
order by LastName, FirstName, MiddleName, PhoneNumberType
SELECT DISTINCT
c.ContactName
,pt.TypeTitle
,(SELECT pn2.PhoneNO + ', '
FROM dbo.PhoneNumber AS pn2
WHERE pn.PhoneType = pn2.PhoneType
AND pn.ContactID = pn2.ContactID
FOR XML PATH ('')
) AS Numbers
FROM dbo.Contact AS c
INNER JOIN dbo.PhoneNumber AS pn
ON c.ContactID = pn.ContactID
INNER JOIN dbo.PhoneType AS pt
ON pn.PhoneType = pt.PhoneTypeID