【问题标题】:SQL Database Table Joining to create an IdealTableSQL 数据库表连接以创建 IdealTable
【发布时间】:2018-01-06 09:50:13
【问题描述】:

我需要一些帮助才能加入我目前拥有的表格。

请假、加班时间和花名册日期、EmployeeID需要匹配

注意:ShiftDuration 设置为默认值 = 8.25

注意:请假和加班表只有在员工申请请假和加班时才会有条目。

Employee
EmplyeeeID | Username | Password | GivenName | FamilyName | TeamID | ContactNo | StaffType
------------------------------------------------------------------------------------------
  123         123        abc        John          Snow        1         999          1
  1234        1234       abcd       Jack         Waller       2         223          1 
  12345       12345      abcde       Ali           Saw        1         123          1
  123456      123456     abcdef     Peter         Peter       2         223          1
  1234567     1234567    abcdeg     Bryan         Peter       1         333          1


Roster
Duty_ID | EmployeeID |      Date        | ShiftType | ShiftDuration
--------------------------------------------------------------------
   2       123             2018-05-05         1          8.25
   4       1234            2018-05-04         1          8.25
   5       12345           2018-05-05         1          8.25
   7       123456          2018-05-04         1          8.25
   8       1234567         2018-05-05         1          8.25


Overtime
OTID | EmployeeID |     Date     | OT_Duration | OT_Reason
------------------------------------------------------------
 2        1234        2018-05-04        2        Cover Duty

Leave
LeaveID | EmployeeID |   Date    | Duration_Off | Reason
----------------------------------------------------------
 3            123      2018-05-05        2         NIL


IdealTable (Via Query)
   Date    | EmployeeID | GivenName | FamilyName | TeamID | ShiftType | ShiftDuration | Duration_Off | OT_Duration | Total_Hours
---------------------------------------------------------------------------------------------------------------------------------
2018-05-05      123         John         Snow         1         1             8.25            2             0            6.25
2018-05-04      1234        Jack        Waller        1         1             8.25            0             2            10.25
2018-05-05      12345       Ali           Saw         1         1             8.25            0             0            8.25
2018-05-04      123456      Peter         Peter       1         1             8.25            0             0            8.25
2018-05-05      1234567     Bryan         Peter       1         1             8.25            2             0            8.25

我有 4 张表,分别是 Employee、Leave、Overtime、Roster

Employee
-EmployeeID (PK)
-Username
-Password
-GivenName
-FamilyName
-TeamID
-ContactNo
-StaffType

Leave
-LeaveID (PK)
-EmployeeID (FK)
-Date
-Duration_Off
-Reason

Overtime
-OTID (PK)
-EmployeeID (FK)
-Date
-OT_Duation
-OT_Reason

Roster
-DutyID (PK)
-EmployeeID (FK)
-Date
-ShiftType
-Shift Duration (Default Value = 8.25)

我想要做的是使用 Query 连接这 4 个表中的数据

Ideal Table
-Date (From Leave, Overtime and Roster Table)
-EmployeeID (Employee Table)
-GivenName (Employee Table)
-FamilyName (Employee Table)
-TeamID (Employee Table)
-ShiftType (Roster Table)
-ShiftDuration (Roster Table)
-Duration_Off (Leave Table)
-OT_Duration (Overtime Table)
-Total_Hours (Calculation from joint table [(ShiftDuration + OT_Duration) - Duration_Off]

My database diagram design 请忽略 TimeData 表,因为我最初想使用 TimeData 表来实现 IdealTable

我当前的查询

USE [SMRT Dashboard]
GO

;With Dates
AS
(
SELECT [Date] FROM dbo.Roster
UNION 
SELECT [Date] FROM dbo.Leave
UNION
SELECT [Date] FROM dbo.Overtime
),
Work_Matrix
AS
(
SELECT EmployeeID,[Date],ShiftType,ShiftDuration,CAST(NULL AS Decimal(30,2)) AS Duration_Off,CAST(NULL AS Decimal(30,2)) AS OT_Duration
FROM dbo.Roster
UNION ALL
SELECT EmployeeID,[Date], NULL, NULL,Duration_Off
FROM dbo.Leave
UNION ALL
SELECT EmployeeID,[Date],NULL,NULL,NULL,OT_Duration
FROM dbo.Overtime
)

SELECT d.[Date],
e.EmployeeID,
e.GivenName,
e.FamilyName,
e.TeamID,
w.ShiftType,
w.ShiftDuration,
w.Duration_Off,
w.OT_Duration,
w.Total_Hours
FROM  Dates d
INNER JOIN
(
SELECT EmployeeID,
[Date],
MAX(ShiftType) AS ShiftType,
SUM(ShiftDuration) AS ShiftDuration,
SUM(Duration_Off) AS Duration_Off,
SUM(OT_Duration) AS OT_Duration,
SUM(ShiftDuration) + SUM(OT_Duration) - SUM(Duration_Off) AS Total_Hours
FROM Work_Matrix
GROUP BY EmployeeID,
[Date]
)w
ON d.[Date] = w.[Date]
JOIN dbo.Employee e
ON e.EmployeeID = w.EmployeeID

当前错误:

Msg 205, Level 16, State 1, Line 4
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.

【问题讨论】:

  • 到目前为止你尝试了什么?你能发布你的尝试吗
  • 从查询中删除星号。
  • Select * 将从所有引用的表中选择所有字段,如果你真的想要你应该在 * 之后添加一个 , 。
  • 如果您希望有人给您一个实际有效的答案,您应该将示例数据作为文本(或添加到 sqlfiddle)与基于示例数据的预期输出一起添加到您的问题中。
  • @envals,这只是根据我发现的最方便的命名约定的一部分供您考虑的提示 - 其他人可能不同意,所以我不想推荐它。在您现有的数据库设计中工作,您只需按照我解释的那样限定列引用。

标签: sql sql-server database join


【解决方案1】:

我尚未对此进行测试,但您现在可以检查一下。希望您的问题能得到解决。

SELECT 
a.EmployeeID,
a.GivenName,
a.FamilyName,
a.TeamID,
d.ShiftType,
d.ShiftDuration,
b.Duration_Off,
c.OT_Duration,
b.Date,
(d.ShiftDuration + c.OT_Duration) - b.Duration_Off as Total_Hours
FROM Employee a
INNER JOIN Roster d ON  a.EmployeeID = d.EmployeeID 
LEFT JOIN Leave b ON a.EmployeeID = b.EmployeeID 
LEFT JOIN Overtime c ON  a.EmployeeID = c.EmployeeID 

我假设Date 在所有三个表(休假、加班和花名册表)中都相同

【讨论】:

  • 有效!但我没有得到任何数据,因为我的假期,加班都是空的。是否可以在这些表为空的情况下显示数据? Screenshot
  • 检查所有表是否有数据+检查ID是否至少有一个相同,那么你应该有一些东西:)
  • 在线查找集合论,记住连接表现为交集
  • @dipakdutta Leave And Overtime 不应该一直有数据,因为只有在员工申请或离职或主管将他们添加到加班列表时才应该有数据。
【解决方案2】:

试试这个查询:

select 
l.Date,
o.Date,
r.Date,
e.EmployeeID,
e.GivenName,
e.FamilyName,
e.TeamID,
r.ShiftType,
r.ShiftDuration,
l.Duration_Off,
o.OT_Duration,
((r.ShiftDuration+o.OT_Duration)-l.Duration_Off) as Total_Hours
FROM Employee e
INNER JOIN Leave l ON e.EmployeeID = l.EmployeeID 
INNER JOIN Overtime o ON  e.EmployeeID = o.EmployeeID 
INNER JOIN Roster r ON  r.EmployeeID = r.EmployeeID;

【讨论】:

    【解决方案3】:

    试试这个查询!你会得到正确的输出。

    SELECT 
    e.EmployeeID AS 'Emp ID',
    e.GivenName AS 'Emp Name',
    l.Date AS Date,
    e.FamilyName AS 'Family Name',
    e.TeamID AS 'Team ID',
    r.ShiftType AS 'Shift Type',
    r.ShiftDuration AS 'Shift Duration',
    l.Duration_Off AS 'Duration Off',
    o.OT_Duration AS 'OT Duration',
    (r.ShiftDuration + o.OT_Duration) - l.Duration_Off as 'Total Hours'
    FROM 
    Employee e,
    Leave l,
    Overtime o,
    Roster r
    WHERE
    e.EmployeeID = l.EmployeeID
    AND
    e.EmployeeID = o.EmployeeID
    AND
    e.EmployeeID = r.EmployeeID
    

    【讨论】:

      【解决方案4】:

      我认为这里的问题是员工可能有休假、可能有加班,或者两者都没有。通过使用 INNER JOIN,您可以将一组员工筛选为有休假、名册和加班的员工。

      我使用您提供的数据创建了一个 SqlFiddle(请参阅 here),它应该可以让您更接近。

        SELECT 
          COALESCE(r.Date, o.Date, l.Date) as Date,
          e.EmployeeID,
          e.GivenName,
          e.FamilyName,
          e.TeamID,
          r.ShiftType,
          r.ShiftDuration,
          IFNULL(l.Duration_Off, 0) as Duration_Off,
          IFNULL(o.OT_Duration, 0) as OT_Duration,
          r.ShiftDuration + IFNULL(o.OT_Duration, 0) - IFNULL(l.Duration_Off, 0) as Total_Hours
        FROM Employee e
        INNER JOIN Roster r on
          e.EmployeeID = r.EmployeeID
        LEFT JOIN Overtime o on
          e.EmployeeID = o.EmployeeID
        LEFT JOIN `Leave` l on
          e.EmployeeID = l.EmployeeID
      

      此查询无法解决一些注意事项:

      • 如果员工有多个休假条目或多个加班条目,则此人将被列出 N 次。您可以使用 GROUP BY 语句来处理此问题
      • 您问题中的示例数据没有正确协调。例如,员工 1234 在 2018 年 5 月 4 日换班,在 2018 年 5 月 5 日加班,但在 2018 年 5 月 4 日获得 10.25。

      如果您使用 TimeData,这会变得容易得多(假设每个员工每个日期一个记录):

      SELECT 
        COALESCE(r.Date, o.Date, l.Date) as Date,
        e.EmployeeID,
        e.GivenName,
        e.FamilyName,
        e.TeamID,
        r.ShiftType,
        IFNULL(r.ShiftDuration, 0) as ShiftDuration,
        IFNULL(l.Duration_Off, 0) as Duration_Off,
        IFNULL(o.OT_Duration, 0) as OT_Duration,
        IFNULL(r.ShiftDuration, 0) + IFNULL(o.OT_Duration, 0) - IFNULL(l.Duration_Off, 0) as Total_Hours
      from TimeData t
      INNER JOIN Employee e on
        t.EmployeeID = e.EmployeeID
      LEFT JOIN Roster r on
        t.Duty_ID = r.Duty_ID
      LEFT JOIN Overtime o on
        t.OTID = o.OTID
      LEFT JOIN `Leave` l on
        t.LeaveID = l.LeaveID 
      

      可以在here找到示例SqlFiddle

      【讨论】:

      • 你建议我如何使用 TimeData?我不知道如何使用它们。因为我想不出任何在没有任何输入的情况下使用 TimeData 表的方式。
      • 您是否为 TimeData 测试数据?从您的数据库图中,它似乎代表了一种将给定员工的各种表联系在一起的方式。在我的第二个查询中,我使用 TimeData 将表连接在一起并填充适当的字段,而无需执行 GROUP BY。
      • 我没有 TimeData 的测试数据,因为根据我对使用 TimeData 表的理解,我需要手动输入不同的 ID。
      猜你喜欢
      • 1970-01-01
      • 2010-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多