2017-09-19 8 views
-2

サブクエリは複数の値を返し、エラーを返します。動作しますサブクエリが2つ以上の値を返しました。SUM(dbo.SalarySettingsBreakup.Amount)を含むサブクエリAS AmountSSB

(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

希望は、これを試してみてください。

(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) 
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をサブクエリに関連付ける必要があります。副問合せを相関させなかったため、外部問合せの各行に対して複数の行が生成され、エラーが発生します。

さらに、相関性についての理解が不足すると、複雑さと論理的なミスが追加されます(正確に相関すると隠蔽されます)。サブクエリに従業員テーブルを含める必要はありません。メイン問合せの従業員表と関連付けるので、重複しています。さらに、外部クエリの行ごとに単一のスカラ値を生成することを目的としているため、サブクエリでグループ化する必要はありません。最後に、サブクエリに参加する外部の目的はありません。 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を読むの混乱につながります。

関連する問題