子查询返回的值超过1。包含SUM的子查询(dbo.SalarySettingsBreakup.Amount)AS AmountSSB

时间:2017-09-19 11:11:58

标签: sql sql-server

我的子查询返回多个值并给出错误。

(SELECT dbo.employee.id, 
        dbo.employee.employeecode, 
        dbo.employee.firstname, 
        dbo.employee.departmentid, 
        dbo.salarysettings.monthlyoffered, 
        dbo.salarysettings.id       AS SalarySettingsID, 
        (SELECT Sum(amount) AS AmountVP 
         FROM   voucherprocesses 
         WHERE  vouchertypeid = 2 
                AND employee = dbo.employee.id 
                AND voucherdate BETWEEN '9/1/2017 12:00:00 AM' AND 
                                        '9/30/2017 12:00:00 AM' 
         GROUP  BY employee)        AS SalaryAdvance, 
        (SELECT Sum(dbo.salarysettingsbreakup.amount) AS AmountSSB 
         FROM   dbo.employee 
                LEFT JOIN dbo.salarysettings 
                       ON dbo.employee.id = dbo.salarysettings.employee 
                LEFT JOIN dbo.salarysettingsbreakup 
                       ON dbo.salarysettings.id = 
                          dbo.salarysettingsbreakup.salarysetting 
         WHERE  dbo.salarysettingsbreakup.paymenttype = 2 
                AND dbo.salarysettingsbreakup.isactive = 1 
         GROUP  BY dbo.employee.id) AS TotalDeduction, 
        (SELECT CASE 
                  WHEN employee.joiningdate BETWEEN 
                       '9/1/2017 12:00:00 AM' AND '9/30/2017 12:00:00 AM' THEN( 
                ( salarysettings.monthlyoffered / 30 ) * ( 30 - 
                ( Datepart(dd, joiningdate) - 1 ) ) ) 
                  ELSE 0 
                END)                AS PayToBank 
 FROM   dbo.employee 
        LEFT JOIN dbo.salarysettings 
               ON dbo.employee.id = dbo.salarysettings.employee 
 WHERE  dbo.salarysettings.isactive = 1) 

2 个答案:

答案 0 :(得分:0)

希望能奏效,试试这个:

(SELECT e.id, 
        e.employeecode, 
        e.firstname, 
        e.departmentid, 
        dbo.salarysettings.monthlyoffered, 
        dbo.salarysettings.id       AS SalarySettingsID, 
        (SELECT Sum(amount) AS AmountVP 
         FROM   voucherprocesses 
         WHERE  vouchertypeid = 2 
                AND voucherprocesses.employee = e.id 
                AND voucherdate BETWEEN '9/1/2017 12:00:00 AM' AND 
                                        '9/30/2017 12:00:00 AM' 
         )        AS SalaryAdvance, 
        (SELECT Sum(dbo.salarysettingsbreakup.amount) AS AmountSSB 
         FROM   dbo.employee e2
                LEFT JOIN dbo.salarysettings 
                       ON e2.id = dbo.salarysettings.employee

                LEFT JOIN dbo.salarysettingsbreakup 
                       ON dbo.salarysettings.id = 
                          dbo.salarysettingsbreakup.salarysetting 
                       AND dbo.salarysettingsbreakup.paymenttype = 2
                       AND dbo.salarysettingsbreakup.isactive = 1
         WHERE e2.id = e.id
         ) AS TotalDeduction, 
        (SELECT CASE 
                  WHEN employee.joiningdate BETWEEN 
                       '9/1/2017 12:00:00 AM' AND '9/30/2017 12:00:00 AM' THEN( 
                ( salarysettings.monthlyoffered / 30 ) * ( 30 - 
                ( Datepart(dd, joiningdate) - 1 ) ) ) 
                  ELSE 0 
                END)                AS PayToBank 
 FROM   dbo.employee e
        LEFT JOIN dbo.salarysettings 
               ON e.id = dbo.salarysettings.employee 
 WHERE  dbo.salarysettings.isactive = 1) 

答案 1 :(得分:0)

你需要学习很多东西。您需要了解子查询的工作方式以及外连接。由于2个问题,以下是错误的。

(SELECT Sum(dbo.salarysettingsbreakup.amount) AS AmountSSB 
     FROM   dbo.employee 
            LEFT JOIN dbo.salarysettings 
                   ON dbo.employee.id = dbo.salarysettings.employee 
            LEFT JOIN dbo.salarysettingsbreakup 
                   ON dbo.salarysettings.id = 
                      dbo.salarysettingsbreakup.salarysetting 
     WHERE  dbo.salarysettingsbreakup.paymenttype = 2 
            AND dbo.salarysettingsbreakup.isactive = 1 
     GROUP  BY dbo.employee.id) AS TotalDeduction, 

首先,您没有正确关联子查询。正如Rahmat发布的那样(但没有解释),您需要将外部查询中的员工ID与子查询相关联。因为您没有关联子查询,所以它会为外部查询中的每一行生成多行 - 产生错误。

此外,您对相关性缺乏了解会导致您增加复杂性和逻辑错误(当正确关联时会被掩盖)。无需在子查询中包含employee表。由于您将其与主查询中的employee表相关联,因此它是多余的。此外,您不需要按子查询中的任何内容进行分组,因为它旨在在外部查询中为每行生成单个标量值。最后,子查询中没有外部连接的目的。您在salarysettingsbreakup中有匹配的行,或者您没有。内部和外部联接将实现相同的结果 - 如果没有匹配则为NULL。我还质疑你是否需要总结所涉及的表和列名称。您应该搜索有关外连接如何工作的解释以及在where子句中引用未保留表(例如salarysettingsbreakup)中的列时会发生什么。

所以更好的子查询是:

(SELECT Sum(bkp.amount)  
FROM dbo.salarysettings as sset 
INNER JOIN dbo.salarysettingsbreakup as bkp
    ON sset.id = bkp.salarysetting 
    AND bkp.paymenttype = 2
    AND bkp.isactive = 1
WHERE sset.employee = dbo.employee.id) as TotalDeduction, 

请注意包含一些最佳做法。为表提供可读别名,并将其与引用的所有列一起使用。我也鄙视使用表名作为列名的做法 - 这增加了阅读IMO查询的困惑。