如何获得一对多的关系数据?

时间:2017-12-13 12:41:10

标签: sql sql-server

这两个tablesone-to-many关系:

Employee[Table]:
---------------------------------------------------
EmpId   | Name  | Country | Salary  | Email 
--------------------------------------------------
1         John    USA       875847   john@test.com
2         Mike    USA       785487   mike@test.com

Lincense[Table]
----------------------------------------
EmpId   | LicenseType   | LincenseNumber
----------------------------------------
1         LincenseType1   12345678
1         LincenseType2   87654321
1         LincenseType3   78945613
2         LincenseType1   12345678
2         LincenseType2   87654321
2         LincenseType3   78945613


EmployeeDetails[Expected ResulSet]
-----------------------------------------------------------------------------------------------
EmpId   | Name  | Country | LicenseType     | LicenseNumber | Salary    | Email
-----------------------------------------------------------------------------------------------
1         John    USA       LincenseType1         12345678    875847     john@test.com
                            LincenseType2         87654321
                            LincenseType3         78945613
2         Mike    USA       LincenseType1         12345678    785487     mike@test.com
                            LincenseType2         87654321
                            LincenseType3         78945613
----------------------------------------------------------------------------------------------

要获得高于预期格式的结果,最佳实现方式是什么,以便结果只包含一行Employee详细信息和所有相关的License详细信息?

4 个答案:

答案 0 :(得分:2)

这将为您提供帮助。请记住,如果您的empid和薪水为int列,则您只能null或将其设置为0。否则,它必须是string

类型

SQL代码

declare @emp table (empid int,[name] nvarchar(50),Country nvarchar(50),Salary int,[Email] nvarchar(50)
)
insert into @emp
values
(1         ,'John',   'USA',       875847,  'john@test.com'),
(2         ,'Mike',    'USA',      785487,   'mike@test.com')

declare @lic table (empid int, licensetype nvarchar(50),licencenumber int)
insert into @lic
values



(1         ,'LincenseType1',   12345678),
(1         ,'LincenseType2',   87654321),
(1         ,'LincenseType3',   78945613),
(2         ,'LincenseType1',   12345678),
(2         ,'LincenseType2',   87654321),
(2         ,'LincenseType3',   78945613)

select 
empid  = case when rn > 1 then null else x.empid end,
[name] = case when rn > 1 then '' else [name] end,
Country = case when rn > 1 then '' else country end,
licensetype = licensetype,
licencenumber = licencenumber,
Salary = case when rn > 1 then '' else Salary end,
Email = case when rn> 1 then '' else Email end

 from (
select a.empid,[name],country,licensetype,licencenumber,Salary,Email,ROW_NUMBER() over(partition by a.empid order by licensetype) as rn from @emp  a left join @lic b on a.empid = b.empid
)x

SQL更新 如果Lincencetype在第一行总是应该是1,那么就可以这样做。这会更快

select 
empid  = case when licensetype !='LincenseType1' then null else a.empid end,
[name] = case when licensetype !='LincenseType1'  then '' else [name] end,
Country = case when licensetype !='LincenseType1' then '' else country end,
licensetype = licensetype,
licencenumber = licencenumber,
Salary = case when licensetype !='LincenseType1'  then '' else Salary end,
Email = case when licensetype !='LincenseType1'  then '' else Email end


 from @emp  a inner join @lic b on a.empid = b.empid

<强>结果

enter image description here

答案 1 :(得分:0)

这个怎么样?

SELECT Employee.EmpId, Employee.Name, Employee.Country,
       Lincense.LicenseType, Lincense.LincenseNumber,
       Employee.Salary, Employee.Email
  FROM Employee JOIN Lincense
       ON (Employee.EmpId = Lincense.EmpId);

如果您正在查找已显示的空值,最好的方法是在报告工具中执行此操作,而不是尝试在SQL中执行此操作

答案 2 :(得分:0)

SELECT Employee.EmpId, Employee.Name, Employee.Country,
       Lincense.LicenseType, Lincense.LincenseNumber,
       Employee.Salary, Employee.Email
FROM Employee 
JOIN Lincense ON Employee.EmpId = Lincense.EmpId;

会给你相同的结果,但所有行都将填充数据。

SELECT Employee.EmpId, Employee.Name, Employee.Country,
       Lincense.LicenseType, Lincense.LincenseNumber,
       Employee.Salary, Employee.Email
FROM Employee 
LEFT OUTER JOIN Lincense ON Employee.EmpId = Lincense.EmpId;

将为所有员工提供结果,即使没有许可证,您也会通过Lincence的属性中的空值来注意这些行

SELECT Employee.EmpId, Employee.Name, Employee.Country,
       Lincense.LicenseType, Lincense.LincenseNumber,
       Employee.Salary, Employee.Email
FROM Employee 
RIGHT OUTER JOIN Lincense ON Employee.EmpId = Lincense.EmpId;

将为您提供所有许可证的结果,即使员工不在场,您也会通过员工的属性上的空值来注意这些行

如果你需要空行,那么在DB中这样做是不好的做法。获得结果后,在后端代码中处理。或者甚至只在前端显示结果时。

注意它的许可证或许可证,具体取决于您喜欢的英语。

答案 3 :(得分:0)

这不是你想要的,但足够接近:

SELECT A.EMPID, A.NAME, A.COUNTRY, STUFF((SELECT ','+ b.LicenseType FROM License b WHERE A.EMPID = B.EMPID FOR XML PATH('')),1,1,'') AS LicenseType, STUFF((SELECT ','+ C.LicenseNumber FROM License C WHERE A.EMPID = C.EMPID FOR XML PATH('')),1,1,'') AS LicenseNumber, A.Salary, A.Email
FROM Employee A

它不会为您提供空行,但会将LicenseType和LicenseNumber放在以逗号分隔的相同列中。