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,
请注意包含了一些最佳实践。为表指定一个可读的别名,并将其用于引用的所有列。我还鄙视使用表名作为列名的做法——这会增加读取查询的混乱