我的子查询返回多个值并给出错误。
(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)
答案 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查询的困惑。