Sql 子查询返回了多个值。包含SUM(dbo.SalarySettingsBreakup.Amount)作为AmountSSB的子查询

Sql 子查询返回了多个值。包含SUM(dbo.SalarySettingsBreakup.Amount)作为AmountSSB的子查询,sql,sql-server,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 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) 

希望能奏效,试试这个:

(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) 

你有很多东西要学。您需要了解子查询以及外部联接是如何工作的。由于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, 
请注意包含了一些最佳实践。为表指定一个可读的别名,并将其用于引用的所有列。我还鄙视使用表名作为列名的做法——这会增加读取查询的混乱