【问题标题】:SQL query to find the highest paid salary for each lanaugesSQL查询查找每种语言的最高薪水
【发布时间】:2013-05-14 07:12:00
【问题描述】:

由于我不是编写 SQL 查询的专家,因此需要帮助。 我有一个名为程序员的表,其结构和数据如下所示:

PNAME,PROF1,PROF2,SALARY

在 prof1 中的数据是:

PASCAL,CLIPPER,COBOL,CPP,COBOL,PASCAL,ASSEMBLY,PASCAL,BASIC,C,PASCAL,FOXPRO。

在 prof2 中的数据是:

BASIC,COBOL,DBASE,DBASE,ORACLE,DBASE,CLIPPER,C,DBASE,COBOL,ASSEMBLY,BASIC,C.

在工资数据中有:

3200,2800,3000,2900,4500,2500,2800,3000,3200,2500,3600,3700,3500。

我需要一个查询来显示每种语言的最高薪程序员的姓名,这意味着我需要显示每种语言的最高薪水和人名。 我尽力得到结果,但没有得到答案。 你能帮帮我吗?

【问题讨论】:

标签: sql sql-server greatest-n-per-group


【解决方案1】:
select lang.prof1, max(lang.Max_Sal) from (
select prof1, max(salary) as Max_Sal from programmer group by PROF1
union
select prof2, max(salary) as Max_Sal from programmer group by PROF2) as lang group by lang.PROF1

【讨论】:

  • 请注意您的格式。为了便于阅读,代码应格式化为代码。
【解决方案2】:

您的数据集标准化很差,这种情况有时会发生,但出于性能原因值得修改。

要获得您要查找的查询,您需要派生一组所有不同的语言,提取最高薪水的标识符,然后引用该薪水的程序员。有多种方法可以实现这一点,最简单的方法可能是使用三个子查询。

SELECT 
  lang.prof,
  (
    SELECT TOP 1 pname
    FROM programmer
    WHERE prof1 = lang.prof OR prof2 = lang.prof
    ORDER BY salary DESC
  ) as Name,
  (
    SELECT MAX(Salary)
    FROM programmer
    WHERE prof1 = lang.prof OR prof2 = lang.prof
  ) as MaxSalary
FROM (
  SELECT prof1 as prof FROM programmer 
  UNION
  SELECT prof2 as prof FROM programmer 
) AS lang

请注意,此查询优化,远非查询表的最有效方式。如果可能,请重新构建数据结构,让程序员、语言及其熟练程度分别放在不同的表中。

具有嵌套子查询的更简洁的实现。更多查询,但您通过直接引用查询 Programmer 并且可以添加任意行。

SELECT 
  Lang.prof,
  P.PName,
  P.Salary
FROM 
(
    SELECT LL.prof, MAX(sP.salary) as MaxSalary
    (
      SELECT prof1 as prof FROM programmer 
      UNION
      SELECT prof2 as prof FROM programmer 
    ) as LL
    INNER JOIN programer sP
        ON LL.prof = sP.prof1 OR LL.prof = sP.prof2
    GROUP BY LL.prof
) as Lang
INNER JOIN programmer P
  ON (Lang.prof = P.prof1 OR P.prof2)
  AND lang.MaxSalary = P.salary

【讨论】:

    【解决方案3】:

    虽然我喜欢 Gordon 的回答,但您可以使用公用表表达式和简单的左连接;

    WITH cte AS (
      SELECT PNAME, SALARY, PROF1 PROF FROM programmer
      UNION 
      SELECT PNAME, SALARY, PROF2      FROM programmer
    )
    SELECT p1.PNAME, p1.PROF, p1.SALARY
    FROM cte p1
    LEFT JOIN cte p2
      ON p1.PROF = p2.PROF AND p1.SALARY < p2.SALARY
    WHERE p2.PNAME IS NULL;
    

    EDIT: An SQLfiddle for testing.

    联合将 PROF1 和 PROF2 展平为单独的行,而左连接基本上可以找到不存在具有相同熟练度的更高薪程序员的程序员。

    【讨论】:

    • 感谢 joachim 的回复.....这是我正在寻找的查询......它给了我想要的输出......谢谢
    【解决方案4】:

    函数row_number() 是最好的方法。

    select t.*
    from (select t.*,
                 row_number() over (partition by language order by salary desc) as seqnum
          from t
         ) t
    where seqnum = 1;
    

    如果有多个程序员的薪水相同,则返回其中一个。如果您想要所有这些,请使用dense_rank() 而不是row_number()

    在重新阅读查询时,我认为“语言”可能是 prof1prof2。这使查询复杂化。可能最简单的方法是使用窗口函数来获取每个人的最大值,然后比较薪水:

    select t.*
    from (select t.*,
                 max(salary) over (partition by prof1) as max1,
                 max(salary) over (partition by prof2) as max2
          from t
         ) t
    where (salary = max1 and max1 >= max2) or
          (salary = max2 and max2 >= max1)
    

    【讨论】:

    • 您能指出row_number 的文档吗?我从未听说过它,我很想知道它是如何工作的
    • 我使用这个查询:-select * from row_number(partition by prof1) as sal from developer......但无法比较 prof1 和 prof2......你的查询似乎好,我会测试它并让您知道结果....感谢您的帮助....
    • row_number() 在这里不合适,除非他想为每种语言运行多个查询。大多数 SQL 实现都包含更简单的 SELECT TOP 1SELECT ... LIMIT 1 语法。
    • @DougM 。 . .当您尝试从每个 group 中获取最高价值时,这些方法效果不佳。
    • @DougM 。 . .我非常不同意单列的情况。在支持它们的数据库上,窗口函数通常比聚合/连接方法更快。此外,您还可以在组内选择一个“最佳”匹配或“所有最佳”匹配(row_number()rank()/dense_rank())。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 2010-09-26
    相关资源
    最近更新 更多