【问题标题】:SQL server query joinsSQL 服务器查询连接
【发布时间】:2013-11-04 21:05:17
【问题描述】:

目标 - 列出每个部门的男性平均工资和女性平均工资。显示部门名称和编号。

 select AVG(salary) as 'Avg salary for men' 
   From [Enterprise].[dbo].[Employee]JOIN [Enterprise].[dbo].[Department]
   ON Employee.EMPNO = Department.deptNo
   where SEX = 'm'

还在学习连接,不确定我是否需要外连接?我如何让它按部门列出平均值?

【问题讨论】:

  • Employee.EMPNO = Department.deptNo?,这个好像不太对,能列出Employee表的列吗?

标签: sql join outer-join


【解决方案1】:

我假设你打算通过 deptNo 加入。

SELECT Department.Name, AVG(salary) as 'Avg salary for men' 
FROM [Enterprise].[dbo].[Employee]
JOIN [Enterprise].[dbo].[Department]
ON Employee.deptNo= Department.deptNo
WHERE SEX = 'm'
GROUP BY Department.Name

这将显示男性每个部门的平均值。您可以对女性执行相同的操作,并使用UNION 将她们包含在查询中。或者添加到您的 GROUP BY 性别,并完全删除 WHERE 子句。

GROUP BY 的列表通常会匹配SELECT 列表中的非聚合列。在这种情况下,它只是 Department.Name。

【讨论】:

  • 如果您使用 UNION 方法,请使用 UNION ALL,因为这两组记录应该是互斥的,除非您的系统允许您为每人选择多个性别。 UNOIN ALL 明显更快。
【解决方案2】:

好吧,首先,您似乎在JOIN 上使用了来自Employee 的错误列。也就是说,您的查询应该是这样的:

SELECT  D.deptNo,
        D.deptName,
        AVG(CASE WHEN E.SEX = 'm' THEN salary END) [Avg salary for men],
        AVG(CASE WHEN E.SEX = 'f' THEN salary END) [Avg salary for women]
FROM [Enterprise].[dbo].[Employee] E
INNER JOIN [Enterprise].[dbo].[Department] D
    ON E.deptNO = D.deptNo     -- use the right column from Employee here
GROUP BY D.deptNo,
         D.deptName

【讨论】:

    【解决方案3】:
    SELECT Employee.EMPNO, Department.Name, SEX, AVG(salary) as [Avg salary] 
    FROM [Enterprise].[dbo].[Employee]JOIN [Enterprise].[dbo].[Department]
       ON Employee.EMPNO = Department.deptNo
    GROUP BY Employee.EMPNO, Department.Name, SEX
    

    这将为您获取数据,您可以从这里随意格式化。

    【讨论】:

      【解决方案4】:

      SQL OUTER JOIN 子句是 SQL JOIN 子句的一种变体,它允许 SELECT 语句访问多个表。 JOIN 子句控制表的链接方式。它是 SQL FROM 子句的限定符。因此,您需要 OUTER JOIN 在您的情况下。如果需要,您可以访问link 了解更多信息。

      要获得按部门平均列出的输出,只需将其添加到查询的末尾:

      ORDER BY Department.deptNo

      【讨论】:

        【解决方案5】:

        没有人解释过某些部门可能没有男性或女性。

        SELECT  D.deptNo,
                D.deptName,
                Coalesce(AVG(CASE WHEN E.SEX = 'm' THEN salary END), 0) [Avg salary for men],
                Coalesce(AVG(CASE WHEN E.SEX = 'f' THEN salary END, 0)) [Avg salary for women]
        FROM [Enterprise].[dbo].[Department] D
        LEFT JOIN [Enterprise].[dbo].[Employee] E
            ON E.deptNO = D.deptNo     -- use the right column from Employee here
        GROUP BY D.deptNo,
                 D.deptName
        

        【讨论】:

          【解决方案6】:

          正如所指出的,您的加入条件没有意义,您正在将员工编号加入部门编号,这将不匹配(或将,但不会实现您想要的逻辑)。

          SELECT
            d.name
          , AVG(e_man.salary) avg_man
          , AVG(e_woman.salary) avg_woman
          FROM department d
          LEFT OUTER JOIN employee e_man ON e_man.deptNo = d.deptNo AND e_man.sex = 'm'
          LEFT OUTER JOIN employee e_woman ON e_woman.deptNo = d.deptNo AND e_woman.sex = 'f'
          GROUP BY d.name
          

          在这里您加入两次,一次加入男性行,一次加入女性行,并根据它们计算平均值。如果没有任何男性/女性,则使用 OUTER 连接。


          注意:我的查询将为每个部门返回一行,男性和女性的平均值为 2 列。替代解决方案是为每个部门返回 0-2 行,每个性别有单独的行,并列出每行/性别的相关薪水。


          编辑:人们似乎非常不满意的替代子查询解决方案。根据我的经验,有时子查询是正确的答案,有时连接是正确的答案,只要不牺牲性能,您通常会使用最适合您的逻辑目标/表示的任何一个。无论如何,您正在使用的 RDBMS 的优化器通常会重写它。与往常一样,最好检查一下计划,看看发生了什么。

          SELECT
            d.name
          , (
              SELECT AVG(e1.salary)
              FROM employee e1
              WHERE e1.sex = 'm'
              AND e1.deptNo = d.deptNo
            ) avg_man
          , (
              SELECT AVG(e2.salary)
              FROM employee e2
              WHERE e2.sex = 'f'
              AND e2.deptNo = d.deptNo
            ) avg_woman
          FROM department d
          

          【讨论】:

          • 这是正确的,有一个选项可以通过 OUTER JOIN 来实现
          • -1 - SELECT 中的子查询不应该是第一个选项。
          • SUbselect 是我用过的最后一个选项。为了任何东西。子选择在它们的操作方式上就像游标。连接查询很好,但不建议子选择。
          【解决方案7】:
          Query1 :
          
          SELECT Table1.*, Table2.[Roll no],Table2.Address,Table2.City
          FROM (Table1 right JOIN Table2 ON Table1.[roll no] = Table2.[roll no] and Table1.[status] = Table2.[status]) 
          where Table1.Status="New" or Table2.status="New"
          UNION SELECT Table1.*,Table2.[roll no], table2.Address,table2.City
          FROM (Table1 left JOIN Table2 ON Table1.[roll no] = Table2.[roll no] and Table1.[status] = Table2.[status])
          where Table1.Status="New" or Table2.status="New";
          
          
          Qury2:
          
          SELECT Table3.*,table4.[roll no],Table4.Sports_id,Table4.Name
          FROM (Table3 right JOIN Table4 ON Table3.[roll no] = Table4.[roll no] and Table3.[status] = Table4.[status]) 
          where Table3.Status="New" or Table4.status="New"
          UNION SELECT Table3.*,table4.[roll no],Table4.Sports_id,Table4.Name
          FROM (Table3 left JOIN Table4 ON Table3.[roll no] = Table4.[roll no] and Table3.[status] = Table4.[status])
          where Table3.Status="New" or Table4.status="New";
          
          
          Query3:
          
          SELECT * 
          FROM (Query2 right JOIN Query3  ON Query2.[Table1.roll no] = Query3.[table3.roll no]) 
          UNION SELECT *
          FROM (Query2 left JOIN Query3  ON Query2.[Table1.roll no] = Query3.[table3.roll no]);
          
          
          Query4:
          
          SELECT Query4.* INTO Final_table
          FROM Query4;
          
          
          Query5:
          
          UPDATE Final_Table SET Query2_Status = "New"
          WHERE Query2_Status is null or Query2_status="";
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-10-21
            • 2011-05-04
            • 1970-01-01
            相关资源
            最近更新 更多