n到n关系如何在一行中获得结果

时间:2012-04-24 16:55:51

标签: sql sql-server-2008 tsql

所以我有一个可以在很多公司工作的员工,所以我有一个n to n的关系,我怎样才能获得一个员工工作的公司,只用一行sql?

example
table - employee
Employeeid  employeename
1             mike

table company
companyId  CompanyName
1           cocacola
2             nokia
3              intel

table employeeCompany
id   employeeid  companyid
1       1            1
2       1            2
3       1            3

我想到了但不能

select Employeeid  , companyid 
from employeeCompany 
where employeeid  = 1 
group by Employeeid  , companyid

2 个答案:

答案 0 :(得分:2)

在Sql Server中最简单的方法是使用FOR XML PATH。神秘的部分.value('text()[1]','nvarchar(max)')处理特殊的xml字符。

select employee.*, companies.*
from Employee
OUTER APPLY
(
    select stuff ((SELECT ', ' + Company.CompanyName
      FROM EmployeeCompany
        INNER JOIN Company
           ON EmployeeCompany.CompanyId = Company.CompanyID
      WHERE EmployeeCompany.employeeid = Employee.EmployeeID
      ORDER BY Company.CompanyName
      FOR XML PATH(''),TYPE).value('text()[1]','nvarchar(max)')
    , 1, 2, '') Companies
) companies

请参阅Sql Fiddle上的演示。

答案 1 :(得分:0)

It sounds like you want something that is similar to mySQL's Group_Concat in SQL Server

如果您正在寻找一种方法来执行此操作,以便每个companyid都在一个单独的列中,那么只有在使用动态SQL时才会遇到困难。那么将它返回给应用程序并让它在自己的逻辑中处理它需要的东西可能更容易吗?

顺便说一下,动态SQL逻辑就会出现这样的情况,以防你想知道......注意它是多么令人讨厌......所以我建议反对它。

select @highestCount = max(count(*))
from employeeCompany
group by Employeeid

declare createtemptable varchar(max), @filltableselect varchar(max), @filltablejoin varchar(max)
declare @currentCount int
set @currentCount = 0
set @createtemptable = 'CREATE TABLE #Temp (EmployeeID INT'
set @filltableselect = 'INSERT INTO #Temp SELECT EmployeeCompany0.EmployeeID, EmployeeCompany0.CompanyID'
set @filltablejoin = 'FROM EmployeeCompany AS EmployeeCompany0'

while(@currentCount < @highestCount)
begin
    set @createtemptable = @createtemptable + ', CompanyID' 
        + CAST(@currentCount AS VARCHAR(2)) + ' INT'

    if(@currentCount > 0)
    begin
        set @filltableselect = @filltableselect + ', EmployeeCompany' 
            + CAST(@currentCount AS VARCHAR(2)) + '.CompanyId'

        set @filltablejoin = @filltablejoin 
            + 'LEFT JOIN EmployeeCompany AS EmployeeCompany' 
            + CAST(@currentCount AS VARCHAR(2)) 
            + ' ON EmployeeCompany0.EmployeeID = EmployeeCompany' 
            + CAST(@currentCount AS VARCHAR(2)) + '.EmployeeID'
    end

    set @currentCount = @currentCount + 1
end
set @createtemptable = @createtemptable + ')'
--This next line can be whatever you need it to be
set @filltablejoin = @filltablejoin + 'WHERE employeeCompany0.EmployeeID = 1'

exec @createtemptable 
exec @filltableselect + @filltablejoin