【问题标题】:Combining 2 queries结合 2 个查询
【发布时间】:2014-06-05 18:57:21
【问题描述】:

我正在尝试导出员工考勤卡信息。出口工作正常,但我试图考虑员工的小费。员工收到的小费是基于工作小时数除以特定部门的总小时数乘以小费金额。例如:

位置 1 有 5 名员工。 2组

经理 - 没有资格获得小费 员工 - 有资格获得小费

我需要获取“员工”组的总小时数,以及员工组中员工的总小时数。

假设员工组本周有 111 小时。员工的工作时间是:

Jim: 22
Bob: 32
Pete: 29
Dave: 28

本周的小费是 100.00 美元

要找到每个成员的提示,我会这样做:

Jim's Tip: 22/111 * 100 = $19.82
Bob's Tip: 32/111 * 100 = $28.83
Pete's Tip: 29/111 * 100 = $26.13
Dave's Tip: 28/111 * 100 = $25.23

最后一部分是经理 Tim,没有资格获得小费,但需要包含在我的导出中。

我可以让查询单独运行:

1) to run for just the groups eligible for tips and calculate the tip
2) to run for all employees leaving tip out.

这是我得到的输出:

Name   Location   OtherNumber   RegHours   OT Hours   TIP
Jim's    1           12345         22          0    $19.82
Bob's    1           12395         32          0    $28.83
Pete's   1           31654         29          0    $26.13
Dave's   1           03948         28          0    $25.23

这是我应该得到的输出:

Name   Location   OtherNumber   RegHours   OT Hours   TIP
Tim      1           30984         40          0    $0
Jim's    1           12345         22          0    $19.82
Bob's    1           12395         32          0    $28.83
Pete's   1           31654         29          0    $26.13
Dave's   1           03948         28          0    $25.23

这是我的代码:

获取“所有”员工的代码,不考虑组

SELECT        ftc.sFirstName + ' ' + ftc.sLastName AS sName, Account.sLocationDesc, Employees.sOtherNumber, SUM(ftc.RegHours) AS RegHours, SUM(ftc.OTHours) 
                         AS OTHours
FROM            dbo.fTimeCard(@StartDate, @EndDate, @DeptList, @iActive, @EmployeeList) AS ftc LEFT OUTER JOIN
                         Employees ON ftc.lEmployeeID = Employees.lEmployeeID LEFT OUTER JOIN
                         Account ON
                             (SELECT        CASE WHEN Employees.lLocationID IS NULL THEN 1 ELSE Employees.lLocationID END AS Expr1
                               FROM            Employees
                               WHERE        (lEmployeeID = ftc.lEmployeeID)) = Account.lLocationID
WHERE        (ftc.RegHours > 0) AND (ftc.RegHours IS NOT NULL)
GROUP BY Account.sLocationDesc, Employees.sOtherNumber, ftc.lEmployeeID, ftc.sLastName, ftc.sFirstName

这是我找出提示的代码,以及每个员工应该从符合条件的组中获得多少:

SELECT        t3.sName, t3.TotalHours, t3.TotalHours / t4.TotalDepartmentHours * @TIP AS Tip
FROM            (SELECT        ftc.sFirstName + ' ' + ftc.sLastName AS sName, SUM(ftc.RegHours) + SUM(ftc.OTHours) AS TotalHours, ftc.lEmployeeID
                          FROM            dbo.fTimeCard(@StartDate, @EndDate, @DeptListTip, @iActive, @EmployeeList) AS ftc LEFT OUTER JOIN
                                                    Employees ON ftc.lEmployeeID = Employees.lEmployeeID LEFT OUTER JOIN
                                                    Account ON
                                                        (SELECT        CASE WHEN Employees.lLocationID IS NULL THEN 1 ELSE Employees.lLocationID END AS Expr1
                                                          FROM            Employees
                                                          WHERE        (lEmployeeID = ftc.lEmployeeID)) = Account.lLocationID
                          WHERE        (ftc.RegHours > 0) AND (ftc.RegHours IS NOT NULL)
                          GROUP BY ftc.lEmployeeID, ftc.sLastName, ftc.sFirstName) AS t3 CROSS JOIN
                             (SELECT        SUM(ftc.RegHours) + SUM(ftc.OTHours) AS TotalDepartmentHours
                               FROM            dbo.fTimeCard(@StartDate, @EndDate, @DeptListTip, @iActive, @EmployeeList) AS ftc LEFT OUTER JOIN
                                                         Employees AS Employees_1 ON ftc.lEmployeeID = Employees_1.lEmployeeID LEFT OUTER JOIN
                                                         Account AS Account_1 ON
                                                             (SELECT        CASE WHEN Employees.lLocationID IS NULL THEN 1 ELSE Employees.lLocationID END AS Expr1
                                                               FROM            Employees
                                                               WHERE        (lEmployeeID = ftc.lEmployeeID)) = Account_1.lLocationID
                               WHERE        (ftc.RegHours > 0) AND (ftc.RegHours IS NOT NULL)) AS t4

这是我的查询结合两者,其中输出不包括“蒂姆”经理”

SELECT        t1.sName, t1.sLocationDesc, t1.sOtherNumber, t1.RegHours, t1.OTHours, t2.Tip
FROM            (SELECT        ftc.sFirstName + ' ' + ftc.sLastName AS sName, Account.sLocationDesc, Employees.sOtherNumber, SUM(ftc.RegHours) AS RegHours, SUM(ftc.OTHours) 
                                                    AS OTHours, ftc.lEmployeeID
                          FROM            dbo.fTimeCard(@StartDate, @EndDate, @DeptList, @iActive, @EmployeeList) AS ftc LEFT OUTER JOIN
                                                    Employees ON ftc.lEmployeeID = Employees.lEmployeeID LEFT OUTER JOIN
                                                    Account ON
                                                        (SELECT        CASE WHEN Employees.lLocationID IS NULL THEN 1 ELSE Employees.lLocationID END AS Expr1
                                                          FROM            Employees
                                                          WHERE        (lEmployeeID = ftc.lEmployeeID)) = Account.lLocationID
                          WHERE        (ftc.RegHours > 0) AND (ftc.RegHours IS NOT NULL)
                          GROUP BY Account.sLocationDesc, Employees.sOtherNumber, ftc.lEmployeeID, ftc.sLastName, ftc.sFirstName) AS t1 INNER JOIN
                             (SELECT        t3.sName, t3.TotalHours, t3.TotalHours / t4.TotalDepartmentHours * @TIP AS Tip, t3.lEmployeeID
                               FROM            (SELECT        ftc.sFirstName + ' ' + ftc.sLastName AS sName, SUM(ftc.RegHours) + SUM(ftc.OTHours) AS TotalHours, ftc.lEmployeeID
                                                         FROM            dbo.fTimeCard(@StartDate, @EndDate, @DeptListTip, @iActive, @EmployeeList) AS ftc LEFT OUTER JOIN
                                                                                   Employees AS Employees_2 ON ftc.lEmployeeID = Employees_2.lEmployeeID LEFT OUTER JOIN
                                                                                   Account AS Account_2 ON
                                                                                       (SELECT        CASE WHEN Employees.lLocationID IS NULL THEN 1 ELSE Employees.lLocationID END AS Expr1
                                                                                         FROM            Employees
                                                                                         WHERE        (lEmployeeID = ftc.lEmployeeID)) = Account_2.lLocationID
                                                         WHERE        (ftc.RegHours > 0) AND (ftc.RegHours IS NOT NULL)
                                                         GROUP BY ftc.lEmployeeID, ftc.sLastName, ftc.sFirstName) AS t3 CROSS JOIN
                                                             (SELECT        SUM(ftc.RegHours) + SUM(ftc.OTHours) AS TotalDepartmentHours
                                                               FROM            dbo.fTimeCard(@StartDate, @EndDate, @DeptListTip, @iActive, @EmployeeList) AS ftc LEFT OUTER JOIN
                                                                                         Employees AS Employees_1 ON ftc.lEmployeeID = Employees_1.lEmployeeID LEFT OUTER JOIN
                                                                                         Account AS Account_1 ON
                                                                                             (SELECT        CASE WHEN Employees.lLocationID IS NULL THEN 1 ELSE Employees.lLocationID END AS Expr1
                                                                                               FROM            Employees
                                                                                               WHERE        (lEmployeeID = ftc.lEmployeeID)) = Account_1.lLocationID
                                                               WHERE        (ftc.RegHours > 0) AND (ftc.RegHours IS NOT NULL)) AS t4) AS t2 ON t1.lEmployeeID = t2.lEmployeeID

您会注意到它基本上是相同的查询,除了我为组使用了不同的参数...我在一个中使用 @DeptList 并将其设置为“全部”,然后使用 @DeptListTip 并将其设置为特定组,在本例中为“员工”

【问题讨论】:

  • @DeptListTip 是字符串还是表值参数?
  • 表值参数

标签: sql sql-server sql-server-2008 sql-server-2005 parameters


【解决方案1】:

由于您只对经理数据有问题,您所要做的就是添加一个联合。

即。你的最终代码

UNION
SELECT 'Tim','1','30984','40','0','$0'

【讨论】:

  • 这将根据位置而改变。例如,在其他地点,我们将有 3 组没有资格获得小费。可能有多达 15 名员工。
  • 这就是第一个查询(t1)。您会看到将其分成 2 个单独的查询,但只需要提示查询中的“提示”列。我想使用 lEmployeeID 进行链接
  • 嗯。或者我可以打破2。并使用工会。我将如何联合上面的 2 个查询?从未使用过联合
  • 尝试使用 With 子句,以便您可以将其限制在临时表中,然后将其过滤掉
  • 其实我不喜欢工会。分解剩余的组将是很困难的......我已经必须在程序循环时按位置分解特定的组。更愿意将 2 个查询混合在一起,并且只使用第二个查询中的“提示”
【解决方案2】:

您可以将结果保存在一个临时表中,这样您就不必一次又一次地调用您的表值函数。此外,尚不清楚您如何识别他/她不符合资格的员工,因此我猜我的解决方案中缺少该部分。如果您提供详细信息,我可以更新它。

无论如何,这是您工作的一种非常简化的形式。 请注意我是如何加入主表的,这样我就不必在 Description 字段上执行 Group By

这可能不会给你想要的结果,但希望它能为你指明正确的方向。

更新: 我已经包含了提示资格检查,但是您的函数应该将 @DepList 作为表字段返回,以便我们可以在查询级别进行过滤,这将节省函数调用 2 次。

DECLARE @tblfTimeCard table(lEmployeeID int, TotalRegHours int, TotalOTHours int, HasTip bit)

-- first we will get all the data and do the basic summing here
-- you are also picking sFirstName and sLastName from Table Valued function
-- while I think same fields can be extracted from Employee master
-- therefore, we should only return the lEmployeeID from TVF
INSERT INTO @tblfTimeCard(lEmployeeID, TotalRegHours, TotalOTHours, HasTip)
    SELECT    lEmployeeiD, SUM(ftc.RegHours) AS TotalRegHours, SUM(ftc.OTHours) AS TotalOTHours, 0 AS HasTip
    FROM    dbo.fTimeCard(@StartDate, @EndDate, @DeptList, @iActive, @EmployeeList) AS ftc 
    WHERE      (ftc.RegHours > 0) AND (ftc.RegHours IS NOT NULL)
    GROUP BY lEmployeeID

-- set HasTip flag for the Employees who are eligible for Tip
UPDATE 
    SET HasTip = 1
FROM    @tblfTimeCard AS F
WHERE    
    Exists(
        SELECT    1
        FROM    dbo.fTimeCard(@StartDate, @EndDate, @DeptListTip, @iActive, @EmployeeList) AS ftc 
        WHERE      ftc.lEmployeeID = F.lEmployeeID
                (ftc.RegHours > 0) AND (ftc.RegHours IS NOT NULL)
    )

SELECT    EDT.lEmployeeID, EDT.TotalRegHours, EDT.TotalOTHours,
        CASE WHEN EDT.HasTip = 1 THEN 
            (EDT.TotalRegHours + EDT.TotalOTHours) / EDT.TotalDepartmentHours * @TIP 
        ELSE
            0
        END AS Tip,
        E.sFirstName + ' ' + E.sLastName AS sName,
        A.sLocationDesc
FROM    (
        SELECT    lEmployeeID, f.TotalRegHours, f.TotalOTHours,
                (
                SELECT     SUM(TotalRegHours, TotalOTHours)
                FROM    @tblfTimeCard
                -- TO DO: here the SUM is happening on whole @tblfTimeCard, while you may
                -- want to group for the particular Group, so you may need to put a filter 
                -- something like
                -- WHERE GroupID = f.GroupID
                ) AS TotalDepartmentHours,
                f.HasTip
        FROM    @tblfTimeCard AS f
        ) AS EDT     -- Employee with Department Totals
        LEFT OUTER JOIN Employees AS E ON EDT.lEmployeeID = EDT.lEmployeeID
        LEFT OUTER JOIN Accounts AS A ON ISNULL(E.lLocationID, 1) = A.lLocationID

【讨论】:

  • 谁有资格获得小费,谁没有资格获得小费取决于“@DeptList”。我需要工资单导出以包括“所有”员工(因为他们都需要支付)。我需要通过将 ID 分配给“@DeptList”来计算小费。在此示例中,“1”是员工组。 “ALL”将包括员工和经理。这有意义吗?
  • @Shmewnix,您正在使用@DepList@DepListTip 调用相同的函数。我想@DepListTip 只会返回有资格获得小费的员工,而@DepList 会返回所有员工?
  • 你是对的。最终,我想显示主查询(所有用户),然后为那些有资格获得小费的用户添加“小费”列。我认为“EmployeeList”可能也需要更改为“EmployeeListTip”。
  • 我需要导出所有员工的工时,以便计算正确的常规工时和加班工时。一些员工会全天打入多个小组。添加多个时间段。这就是为什么必须首先导出所有时间,然后我循环返回以计算小费。想法是将所有这些导出到 Vb.net 中的 csv 如果我在 Query 端处理所有这些,那么在 VB 中就不用担心了。
猜你喜欢
  • 2020-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多