使用Group By返回超过1个值的子查询

时间:2013-06-26 15:12:35

标签: sql sql-server

使用此表和代码创建查询时出现问题, 我知道“GROUP BY Branch.BranchName”导致获得多个记录,但是,如何避免这种情况并在单个查询中执行此操作。 我想要得到的是一张桌子 包含BranchName - 总payedvalue--总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

2 个答案:

答案 0 :(得分:5)

试试这个 -

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

更新:

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

答案 1 :(得分:3)

错误是相当自我解释的,在您的子查询中,您返回多个结果,这是不允许的。如果您在逻辑上考虑是否应该显示哪一行?

您遇到此问题的原因是,即使您按branch.BracnName分组,也没有链接回外部查询,因此您的子查询将返回所有分支的结果。你需要这样的东西:

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

然而你的整个查询冷却如下所示,不需要相关的子查询,如果你可以避免相关的子查询,那么通常是个好主意。在某些DBMS中,优化器可以优化一些子查询并将它们转换为连接,但在最简单的术语中,相关子查询要求子查询对每一行执行一次,这会导致比使用连接更多的开销

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;