简体   繁体   English

SQL Server从不同的表中选择数据

[英]SQL Server Selecting data from different tables

I am trying to make a table for reports which is made up from data from other tables. 我正在尝试为由其他表格中的数据组成的报表制作表格。 The Reports table needs to include info of how many holiday hours and sick hours each site is taken but the employees take hours individually. “报告”表需要包含每个站点需要多少假期和病假时间,但员工要分别花费几个小时的信息。 All these table are connected by foreign key relationship. 所有这些表都是通过外键关系连接的。

[dbo].[Employee]: [dbo]。[员工]:

EmployeeID  |Name            |SiteID         |
------------+----------------+---------------+
1           | Joe            |1              |
2           | Tom            |2              |
3           | Mary           |3              |
4           | Bill           |1              |
5           | 16             |2              |

Site: 现场:

[dbo].[Site]: [dbo]。[网站]:

SiteID      |Site Name       |
------------+----------------+
1           | SiteA          |
2           | SiteB          |
3           | SiteC          |

[dbo].[HolidayRequestForm]: [dbo]。[HolidayRequestForm]:

EmployeeID  |HolidayHours           |
------------+----------------+
1           | 8              |
2           | 16             |
3           | 16             |

[dbo].[SickLeaveRequestForm]: [dbo]。[SickLeaveRequestForm]:

EmployeeID  |SickHours           |
------------+----------------+
1           | 8              |
2           | 8              |
3           | 8              |

I have tried achieve this by using joins and then selecting the relevant data from the different tables, but I'm having no luck. 我试图通过使用联接,然后从不同的表中选择相关数据来实现这一点,但是我没有运气。

SELECT *
FROM [dbo].[Employee]  
   INNER JOIN [dbo].[Site]
     ON [dbo].[Site].SiteID = [dbo].[Employee].SiteID
   INNER JOIN [dbo].[HolidayRequestForm]
              LEFT JOIN [dbo].[SickLeaveRequestForm]
                ON [dbo].[SickLeaveRequestForm].EmployeeID = [dbo]. 
[HolidayRequestForm].EmployeeID
     GROUP BY [dbo].[Site].SiteName

Would I be better off creating a view? 创建视图会更好吗?

Here is the desired result! 这是期望的结果!

SiteName  |Holiday Hours   |Sick Hours
 ---------+----------------+---------------+
Site A    | 8              |8              |
Site B    | 16             |8              |
Site C    | 16             |8              |
SELECT dbo.Site.SiteName,
    SUM(dbo.HolidayRequestForm.HolidayHours) AS HolidayHours,
    SUM(dbo.SickLeaveRequestForm.SickHours) AS SickHours
FROM dbo.Employee INNER JOIN
    dbo.Site ON dbo.Employee.SiteID = dbo.Site.SiteID INNER JOIN
    dbo.HolidayRequestForm ON dbo.Employee.EmployeeID = 
    dbo.HolidayRequestForm.EmployeeID INNER JOIN
    dbo.SickLeaveRequestForm ON dbo.Employee.EmployeeID = dbo.SickLeaveRequestForm.EmployeeID
GROUP BY dbo.Site.SiteName

Would I be better off creating a view? 创建视图会更好吗? It all depends if this is a one-time query or you are going to use that for reporting on a regular basis. 这完全取决于这是一次查询还是要定期使用该报告进行报告。

Also if you want to include all Sites where no employes have taken sick leave or holiday (eg for MSSQL): 另外,如果要包括所有没有员工请病假或休假的站点(例如,对于MSSQL):

SELECT  dbo.Site.SiteName, 
    { fn IFNULL(SUM(dbo.HolidayRequestForm.HolidayHours), 0) } AS HolidayHours, 
    { fn IFNULL(SUM(dbo.SickLeaveRequestForm.SickHours), 0) } AS SickHours
FROM dbo.Employee 
     LEFT OUTER JOIN dbo.HolidayRequestForm ON dbo.Employee.EmployeeID = dbo.HolidayRequestForm.EmployeeID 
     LEFT OUTER JOIN dbo.SickLeaveRequestForm ON dbo.Employee.EmployeeID = dbo.SickLeaveRequestForm.EmployeeID 
    RIGHT OUTER JOIN dbo.Site ON dbo.Employee.SiteID = dbo.Site.SiteID
GROUP BY dbo.Site.SiteName

You can use SUM aggregate function with GROUP BY like following query. 您可以将SUM聚合函数与GROUP BY结合使用,如下所示。

SELECT s.sitename, 
       Sum(hf.holidayhours) AS HolidayHours, 
       Sum(sl.sickhours)       AS SickHours 
FROM   [dbo].[site] s 
       INNER JOIN [dbo].[employee] e 
               ON s.siteid = e.siteid 
       INNER JOIN [dbo].[holidayrequestform] hf 
               ON e.employeeid = hf.employeeid 
       INNER JOIN [dbo].[sickleaverequestform] sl 
               ON sl.employeeid = e.employeeid 
GROUP  BY s.sitename 

Note : 注意事项

  1. * doesn't go with GROUP BY , any non aggregated column you want in select should present in your GROUP BY *不与GROUP BY一起使用,您要在select中选择的任何非聚合列都应出现在GROUP BY
  2. As a best practice, you should use alias names for your tables while joining. 最佳做法是,在连接时,应为表使用别名。

Youre trying to select all the columns from a query that is grouping - you can only select columns that are grouped, or appear in an aggregate function: 您正在尝试从正在分组的查询中选择所有列-您只能选择已分组或出现在聚合函数中的列:

SELECT s.SiteName, SUM(hrf.HolidayHours) as SumHolidayHours, SUM(slrf.SickHours) as SumSickHours
FROM 
   [dbo].[Employee] e 
   INNER JOIN [dbo].[Site] s
     ON s.SiteID = e.SiteID
   LEFT JOIN [dbo].[HolidayRequestForm] hrf
     ON hrf.EmployeeId = e.EmployeeID
   LEFT JOIN [dbo].[SickLeaveRequestForm] slrf
     ON slrf.EmployeeID = e.EmployeeID
 GROUP BY s.SiteName

You were missing an ON condition to one of your joins. 您缺少其中一个联接的ON条件。 I've also added table aliases to reduce the visual clutter and converted both the joins to the hours tables into being left joins just in case an employee doesn't have any records in those tables 我还添加了表别名以减少视觉混乱,以防万一员工在这些表中没有任何记录的情况下,将两个联接都转换为小时表

The important thing to appreciate about grouping queries is that multiple records with the same combination of values in the grouped columns (your sitename) will be collapsed into a single record in the output. 有关对查询进行分组的重要一点是,分组列(您的站点名称)中具有相同值组合的多个记录将在输出中折叠为单个记录。 The aggregate function (SUM MAX MIN AVG etc) defines what to do with all the detailed data as it collapses. 汇总函数(SUM MAX MIN AVG等)定义了折叠后所有详细数据的处理方式。 In this case we are trying to add up the hours by site. 在这种情况下,我们尝试按站点总计时间。 The association is 该协会是

site -> employees -> hours (sick and holiday)

Because there are multiple employees and possibly also multiple hours, but we're grouping on site name, there will be only one row per site in the output, so we need to specify an aggregation to carry out on the other columns. 因为有多个员工,而且可能还有多个小时,但是我们将站点名称分组,所以输出中每个站点只有一行,因此我们需要指定一个汇总以在其他列上进行。 You can't select * from a grouping query, because you can't include all the columns; 您无法从分组查询中选择*,因为您无法包含所有列; you can only include columns that are part of th grouping combination, or an aggregate of the data that went into the group. 您只能包括属于分组组合的一部分的列,或者属于该组的数据的总和。 If you ever want to add more columns to a group query but you don't want to have the group broken down into more fine detail on the grouping keys, you have to instead join the grouped data back to the main tables to get the additional data 如果您想向组查询中添加更多列,但又不想将组分解为有关分组键的更多详细信息,则必须将分组数据重新加入主表以获取其他数据数据

You can try the below query. 您可以尝试以下查询。

create table Employee(EmployeeID int, Name varchar(20), SiteID int)
insert into Employee values
(1, 'Joe', 1),
(2, 'Tom', 2),
(3, 'Mary', 3),
(4, 'Bill', 1),
(5, '16', 2)

create table [Site] (SiteID int, [Site Name] Varchar(20))
insert into [Site] Values
(1, 'SiteA'),
(2, 'SiteB'),
(3, 'SiteC')

Create table HolidayRequestForm(EmployeeID  int, HolidayHours int)
insert into HolidayRequestForm Values
(1, 8),
(2, 16),
(3, 16)

Create table SickLeaveRequestForm(EmployeeID int, SickHours int)
insert into SickLeaveRequestForm Values
(1 ,8),
(2,8),
(3,8)

Select [Site Name], SUM(HolidayHours) as HolidayHours, SUM(SickHours) as 
SickHours
from(
Select 
[Site].[Site Name], HolidayRequestForm.HolidayHours, SickLeaveRequestForm.SickHours
from [Site]
inner join Employee on [Site].SiteId = Employee.SiteId
inner join HolidayRequestForm on HolidayRequestForm.EmployeeID = Employee.EmployeeID
inner join SickLeaveRequestForm on Employee.EmployeeID = SickLeaveRequestForm.EmployeeID
)a group by [Site Name]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM