【问题标题】:Use OVER (PARTITION BY ) instead of Group By使用 OVER (PARTITION BY ) 而不是 Group By
【发布时间】:2014-01-07 12:46:31
【问题描述】:

现在我在我的 sql 查询中使用临时表,但我想使用 Partition By 函数。

我的临时表查询如下:

drop table #Temp;

create table #Temp
(
  NAME varchar(50),
  EMPID varchar(50),
  SS MONEY,
  PP MONEY
);

insert into #Temp
 select * From
 (  
  select
   p1.NAME,
   p1.EMPID,
   case when p1.AmtPayer = 'SELF' then sum(p1.Salary) else 0 end as S,
   case when p1.AmtPayer = 'MANAGER' then sum(p1.Salary) else 0 end as P
  from Candidate p1 
  group by p1.Name, p1.EMPID, p1.AmtPayer
 ) as P;

select 
 t.NAME,
 t.EMPID,
 sum(t.SS) as 'SELF PAID',
 sum(t.PP) as 'PARTY PAID' 
from #Temp t
group by t.NAME, t.EMPID;

我也得到了预期的结果,但我想使用分区函数执行此操作,我尝试过但结果不准确 -

select
 NAME,
 EMPID,
 sum(Salary) over (partition by AmtPayer) as Total
from dbo.Candidate 

输出是:

维维克 0001 300.00 维维克 0001 300.00 维维克 0001 6200.00 维维克 0001 6200.00 维维克 0001 6200.00

但我需要:

维维克 0001 6200.00 300.00

【问题讨论】:

  • 请缩进您的代码,以便它显示为代码并在一定程度上对其进行格式化......这真的很难阅读。
  • 如果你想对结果进行分组,你需要使用 group by。窗口函数的全部目的不是不是“减少”结果集。
  • 无论如何,您都不需要临时表。查找有关 with 语句的内容,它允许您通过 group by 执行 group by(这也将解决您的问题)。

标签: sql-server window-functions


【解决方案1】:

要完全按照你的意愿去做,试试这个:

select
 Name, EmpId,
 sum(case when AmtPayer = 'SELF' then Salary else 0 end) as [Self],
 sum(case when AmtPayer = 'MANAGER' then Salary else 0 end) as [Manager]
from dbo.Candidate
group by Name, EmpId;

您可以在聚合函数中使用 case 语句,这使您可以做很多疯狂的事情:)

但是,正如我在 cmets 中对您的问题所指出的那样,这仅在您预先知道固定数量的 AmtPayer 变体时才有用。

详细说明:partition by 被明确设计不是来减少结果集。它仍将每行返回一行,您无法更改它 - 如果您确实想减少结果集,请改用 group by。结合你可以用聚合函数做的所有复杂的事情,这实际上是一个非常强大的工具——它适用于partition bygroup by。另请注意,partition by 可能比group by 慢得多。事实上,我发现使用 partition by 来获取结果计数(即count over (partition by NULL) 或类似的东西)比简单地执行两个查询要慢得多,一个仅用于计数,另一个用于实际结果。

不要以为自己的方式更好,因为它看起来更聪明 - 始终衡量。分析是你的朋友。像 SQL Server 这样的系统正在做很多优化,一直在尝试为看似愚蠢的查询提供出色的性能:)

【讨论】:

    【解决方案2】:

    我使用了以下查询:

    DROP TABLE #Temp
    CREATE TABLE #Temp(
     NAME VARCHAR(50),
     EMPID VARCHAR(50),
     SS MONEY,
     PP MONEY
    )
    INSERT INTO #Temp
    Select * From(
    SELECT DISTINCT
      NAME,EMPID, 
      SUM(CASE WHEN AmtPayer='SELF' then Salary ELSE 0 end) OVER (PARTITION BY AmtPayer) AS SS ,
      SUM(CASE WHEN AmtPayer='MANAGER' THEN  Salary ELSE 0 end) OVER (PARTITION BY AmtPayer) AS PP
    FROM dbo.Candidate 
    )AS P
    SELECT DISTINCT t.NAME ,t.EMPID ,SUM(t.SS) OVER(PARTITION BY t.NAME,t.EMPID) AS 'SELF PAID',
    SUM(t.PP)  OVER(PARTITION BY t.NAME,t.EMPID) AS 'PARTY PAID' FROM #Temp t
    --GROUP BY t.NAME ,t.EMPID 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多