sakir
sakir

Reputation: 3502

Subquery Returned More Than 1 Value with the Group By

I have some problem creating query with this tables and codes, I know "GROUP BY Branch.BranchName" cause to get multiple records,but,How can avoid this and to do that in single query. what I am trying to get is a table which contains BranchName -- total payedvalue-- total notpayedvalue

SELECT
    (
        SELECT SUM (DeptDesciption.DeptValue)
        FROM dbo.SudentPayments
            INNER JOIN dbo.Student ON dbo.SudentPayments.StudentId = dbo.Student.StudentId
            INNER JOIN dbo.DeptDesciption ON SudentPayments.DeptDesciptionId = DeptDesciption.DeptDesciptionId
            INNER JOIN dbo.Branch on dbo.Branch.BranchId = Student.BranchId
        WHERE SudentPayments.IsDeptPayed = 0
        GROUP BY Branch.BranchName
    ) AS Payed,
    (
        SELECT SUM (DeptDesciption.DeptValue)
        FROM dbo.SudentPayments
            INNER JOIN dbo.Student ON dbo.SudentPayments.StudentId = dbo.Student.StudentId
            INNER JOIN dbo.DeptDesciption ON SudentPayments.DeptDesciptionId = DeptDesciption.DeptDesciptionId
            INNER JOIN dbo.Branch on dbo.Branch.BranchId = Student.StudentId
        WHERE SudentPayments.IsDeptPayed = 1
        GROUP BY Branch.BranchName
    ) AS Notpayed,
    Branch.BranchName
FROM dbo.SudentPayments 
    INNER JOIN dbo.Student ON dbo.SudentPayments.StudentId = dbo.Student.StudentId
    INNER JOIN dbo.DeptDesciption ON SudentPayments.DeptDesciptionId = DeptDesciption.DeptDesciptionId
    INNER JOIN dbo.Branch on dbo.Branch.BranchId = Student.StudentId

Upvotes: 2

Views: 1495

Answers (2)

Devart
Devart

Reputation: 121902

Try this one -

SELECT
      b.BranchName
    , Notpayed = SUM(CASE WHEN sp.IsDeptPayed = 1 THEN d.DeptValue END)
    , Payed = SUM(CASE WHEN sp.IsDeptPayed = 0 THEN d.DeptValue END)
FROM dbo.SudentPayments sp 
JOIN dbo.Student s ON sp.StudentId = s.StudentId
JOIN dbo.DeptDesciption d ON sp.DeptDesciptionId = d.DeptDesciptionId
JOIN dbo.Branch b on b.BranchId = s.StudentId
GROUP BY ALL b.BranchName

UPDATE:

SELECT
      b.BranchName
    , Notpayed = ISNULL(t.Notpayed, 0)
    , Payed = ISNULL(t.Payed, 0)
FROM dbo.Branch b
LEFT JOIN (
     SELECT 
            s.StudentId
          , Notpayed = SUM(CASE WHEN sp.IsDeptPayed = 1 THEN d.DeptValue END)
          , Payed = SUM(CASE WHEN sp.IsDeptPayed = 0 THEN d.DeptValue END)
     FROM dbo.SudentPayments sp
     JOIN dbo.Student s ON sp.StudentId = s.StudentId
     JOIN dbo.DeptDesciption d ON sp.DeptDesciptionId = d.DeptDesciptionId
     GROUP BY s.StudentId
) t on b.BranchId = s.StudentId

Upvotes: 5

GarethD
GarethD

Reputation: 69759

The error is fairly self explanatory, within your subquery you are returning multiple results, which is not allowed. If you think about it logically if there is more than one row which row should be displayed?

The reason you are having this problem is that even though you have grouped by branch.BracnName you have not linked back to your outer query, so your subqueries are returning results for all branches. You would need something like:

SELECT
    (
        SELECT SUM (dd.DeptValue)
        FROM dbo.SudentPayments sp
            INNER JOIN dbo.Student s ON dbo.sp.StudentId = s.StudentId
            INNER JOIN dbo.DeptDesciption dd ON sp.DeptDesciptionId = dd.DeptDesciptionId
        WHERE s.IsDeptPayed = 0
        AND s.BranchID = Branch.BranchID    -- LINK TO OUTER BRANCH TABLE
    ) AS Payed
FROM dbo.Branch

However your entire query cold be rewritten as follows with no need for correlated subqueries, and if you can avoid correlated subqueries then it is usually a good idea. In some DBMS the optimiser can optimise some subqueries away and turn them into joins, but in it simplest terms with a correlated subquery you are asking the subquery to execute once for each row, this leads to much more overhead than using joins

SELECT  Branch.BranchName, 
        Payed = SUM(CASE WHEN SudentPayments.IsDeptPayed = 1 THEN DeptDesciption.DeptValue ELSE 0 END),
        Notpayed = SUM(CASE WHEN SudentPayments.IsDeptPayed = 0 THEN DeptDesciption.DeptValue ELSE 0 END)
FROM    dbo.SudentPayments
        INNER JOIN dbo.Student 
            ON dbo.SudentPayments.StudentId = dbo.Student.StudentId
        INNER JOIN dbo.DeptDesciption 
            ON SudentPayments.DeptDesciptionId = DeptDesciption.DeptDesciptionId
        INNER JOIN dbo.Branch 
            ON dbo.Branch.BranchId = Student.StudentId
GROUP BY Branch.BranchName;

Upvotes: 3

Related Questions