【问题标题】:Max sal to print base on manager_id基于 manager_id 打印的 Max Sal
【发布时间】:2015-11-27 10:24:08
【问题描述】:

我有这张桌子:

id  mgr_id  sal
1   5       5000
2   5       6000
3   6       7000
4   6       8000

我期望这个输出:

id  mgr_id  sal MaX_sal
1   5      5000 6000
2   5      6000 6000
3   6      7000 8000
4   6      8000 8000

基于mgr_id选择max sal并打印在id前面。

提前致谢。

【问题讨论】:

  • 谢谢迪奥戈·罗查。 . .请提出任何答案
  • 请提供有关Max_sal的更多详细信息。它是如何工作的?
  • 不应该是 3、6、7000、8000 吗?
  • 更新了输出请立即查看
  • 这个sal 的id 和group by 基于mgr_id 然后max(sal) 返回到属于id 的前面。

标签: sql sql-server


【解决方案1】:

可能是选择中的子选择(尽管所有子选择都有点慢):

select id, mgr_id, sal, (select max(sal) from mytable n2 
where n2.mgr_id = mytable.mgr_id) as max_sal from mytable 

【讨论】:

    【解决方案2】:

    按 mrg_id 创建一个子表分组以获得每个 mrg_id 的最大 Sal,然后将其与 mrg_id 上的主表连接起来——试试这个:

    declare @table table (id int,mrg_id int,sal decimal(10,0))
    
    insert into @table
    select 1,   5,       5000 union all
    select 2,   5,       6000 union all
    select 3,   6,       7000 union all
    select 4,   6,       8000 
    
    /***** change @table with your table name *****/ 
    SELECT 
    t.id,
    t.mrg_id,
    t.sal,
    t1.max_sal
    FROM @table t
    LEFT JOIN 
    (SELECT 
    mrg_id,
    MAX(sal) max_sal
    FROM @table
    group by 
    mrg_id) t1
    on t.mrg_id=t1.mrg_id
    

    【讨论】:

    • 你为什么使用左连接?
    • @Julien Vavasseur LEFT JOIN 没有伤害。在 SQL Server 的某些版本中,INNER JOIN 会混淆基数估计。你对这个答案投了反对票吗?
    • @Julien Vavasseur 我正在使用左连接,因为我在子表中使用了同一个表并且它的性能更好。没有理由对答案投反对票!!!
    • 抱歉@Amine Zaminex 回复晚了。我刚刚在 2008 年到 2012 年对样本表上的所有答案、随机值、不带 ID 的 PK 或索引 (mgr_id, sal desc) include(id) 或 (mgr_id) include(sal, id) 进行了测试100、1000、10.000 或 100.000 行,不带或带位置(其中 mgr_id = X)。 INNER JOIN 总是提供最好的性能和查询计划,尽管 MAX over 有时会更好一些。 W/o 当有更多行时,LEFT 与 INNER 更接近或相似。使用 Where 时,无论行数如何,INNER 总是比 LEFT 好。 LEFT 和 CTE 给出了相同的计划和性能。
    • 查看之前的评论@Jesús López
    【解决方案3】:

    即使在 SQL Server 6.5 中也可以使用

    SELECT id, mgr_id, sal, 
        (
            SELECT MAX(sal) 
            FROM employees mgr 
            WHERE mgr.mgr_id = emp.mgr_id
        ) AS max_sal
    FROM
       employees emp
    

    这适用于 SQL Server 2005:

    WITH max_sals AS
    (
    
        SELECT mgr_id, MAX(sal) AS max_sal
        FROM employees
        GROUP BY mgr_id
    )
    SELECT emp.*, max_sals.max_sal
    FROM
        employees emp
        LEFT JOIN max_sals
            ON emp.mgr_id = max_sals.mgr_id
    

    这个使用分区:

    SELECT emp.*, MAX(emp.sal) OVER (PARTITION BY emp.mgr_id) AS max_sal
    FROM employees emp
    

    示例数据和表格:

    CREATE TABLE employees
    (
      id int,
      mgr_id int,
      sal int
    
    )
    
    INSERT INTO employees VALUES
    (1,5,5000),
    (2,5,6000),
    (3,6,7000),
    (4,6,8000)
    

    【讨论】:

    • 是的! 6.5 是我使用的第一个 SQL Server 版本。很久以前
    • 相同,但我希望不再需要它:)
    【解决方案4】:

    使用 SQL Server 2012 只需使用以下查询:

    SELECT d.id, d.mgr_id, d.sal, MAX(sal) over(partition by mgr_id)
    FROM @data d
    

    您可以将此查询与 SQL Server

    一起使用
    SELECT d.id, d.mgr_id, d.sal, m.mx
    FROM @data d
    INNER JOIN (
        SELECT mgr_id, mx = MAX(sal) FROM @data
        GROUP BY mgr_id
    ) m
    ON m.mgr_id = d.mgr_id;
    

    SQL Server >= 2005 的另一个选项:

    SELECT d.id, d.mgr_id, d.sal, m.mx
    FROM @data d
    CROSS APPLY (SELECT mx = MAX(sal) FROM @data m WHERE m.mgr_id = d.mgr_id) m(mx)
    

    样本数据:

    Declare @data table([id] int, [mgr_id] int, [sal] int);
    
    INSERT INTO @data([id], [mgr_id], [sal])
    VALUES
        (1, 5, 5000),
        (2, 5, 6000),
        (3, 6, 7000),
        (4, 6, 8000)
    ;
    

    【讨论】:

    • 出于兴趣(目前无法尝试),通过子选择与组的内部连接与选择内的子选择(包含 where)一样快?
    • 在我的虚拟机上,有一个小表,没有索引,子选择,内连接,交叉应用给出类似的结果。
    • 不要认为这是理所当然的。它会因表设计、数据、索引而异......
    【解决方案5】:

    尝试交叉应用,

    SELECT      id,
                mgr_id,
                sal,
                Max_sal
    FROM        #your_table A
    CROSS APPLY (SELECT Max(SAL) AS Max_sal
                 FROM   #your_table B
                 WHERE  B.mgr_id = A.mgr_id)cs 
    

    【讨论】:

      猜你喜欢
      • 2023-03-02
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-14
      • 1970-01-01
      相关资源
      最近更新 更多