选择比较SQL中两行的最大值

时间:2014-12-03 19:06:45

标签: sql-server sql-server-2008

我的表格格式如下:

+--------+------------+---------+-------+
| Entity | Department | Product | Value |
+--------+------------+---------+-------+
| E1     | D1         | P1      |    10 |
| E1     | D1         | P2      |    20 |
| E1     | D1         | P3      |    70 |
| E2     | D2         | P1      |    40 |
| E2     | D2         | P2      |    50 |
| E2     | D2         | P3      |    60 |
+--------+------------+---------+-------+

分组由我想要的每个实体和部门,

  • 选择(具有最高价值)AND的产品(最高值至少是第二个最高值的两倍)。
  • 如果为true,则返回产品和最高值。
  • 如果为false,则返回所有产品及其值。

中级结果:

+--------+------------+---------+-------+
| Entity | Department | Product | Value |
+--------+------------+---------+-------+
| E1     | D1         | P3      |    70 |
| E1     | D1         | P2      |    20 |
| E1     | D1         | P1      |    10 |
| E2     | D2         | P3      |    60 |
| E2     | D2         | P2      |    50 |
| E2     | D2         | P1      |    40 |
+--------+------------+---------+-------+

最终结果:

+--------+------------+---------+-------+
| Entity | Department | Product | Value |
+--------+------------+---------+-------+
| E1     | D1         | P3      |    70 |
| E2     | D2         | P1      |    40 |
| E2     | D2         | P2      |    50 |
| E2     | D2         | P3      |    60 |
+--------+------------+---------+-------+

不确定这是否只能通过SQL实现。如有任何解决方案,请通知我。

3 个答案:

答案 0 :(得分:0)

以下是使用row_number的一种方式。

首先cte根据值

对实体中的条目进行排序

第二次cte检查满足条件(最高值> 2 *第二高值)的所有值

第三个选择从cte和不满足条件的所有其他实体获取行

with cte 
as
(
select row_number() over ( partition by entity order by value desc) as rn,
   entity, department, product, value
from Table1
)
, cte1
as
(
select c1.Entity, C1.department, C1.product, c1.value from 
cte c1
join cte c2
on c1.rn =1
and c2.rn =2
and c1.entity = c2.entity
and c1.value > 2 * c2.value
)
select entity, department, product, value from cte1
union
select entity, department, product, value from cte
where not exists 
( select 1 from cte1
  where cte.entity = cte1.entity
)

答案 1 :(得分:0)

这是sql server的替代方法:

with cte as (
  select *, 
    row_number() over (partition by entity, dept order by value desc) rn,
    max(value) over (partition by entity, dept) topvalue
  from yourtable
  ) 
select entity, dept, product, value
from cte c
where exists (
  select 1
  from cte c2
  where c.rn = 1 
    or (c.dept = c2.dept 
    and c.entity = c2.entity 
    and c2.rn = 2
    and 1.0*c2.topvalue/c2.value <= 2)
)
order by entity, dept, product

答案 2 :(得分:0)

这是另一种可能不使用CTEs的解决方案:

SELECT t1.Entity, t1.Department, t1.Product, t1.Value
 FROM (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY Entity, Department ORDER BY Value DESC) AS productOrder        
     FROM @T ) t1
 LEFT JOIN (
     SELECT w1.Entity, w1.Department, w1.MaxMinusDoubleOfSecondToMax
     FROM (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY Entity, Department ORDER BY Value DESC) AS productOrder,
               (MAX(Value) OVER (PARTITION BY Entity, Department ORDER BY Value DESC))  - 2 * Value AS MaxMinusDoubleOfSecondToMax
     FROM @T ) w1
     WHERE w1.productOrder = 2 ) w2 ON t1.Entity = w2.Entity AND t1.Department = w2.Department
WHERE t1.productOrder = 1 OR w2.MaxMinusDoubleOfSecondToMax < 0

为了解释上述内容,这个嵌套查询:

 SELECT w1.Entity, w1.Department, w1.MaxMinusDoubleOfSecondToMax
 FROM (
 SELECT *, ROW_NUMBER() OVER (PARTITION BY Entity, Department ORDER BY Value DESC) AS productOrder,
           (MAX(Value) OVER (PARTITION BY Entity, Department ORDER BY Value DESC))  - 2 * Value AS MaxMinusDoubleOfSecondToMax
 FROM @T ) w1
 WHERE w1.productOrder = 2

生成此结果集:

Entity  Department  MaxMinusDoubleOfSecondToMax
------------------------------------------------
E1      D1          30
E2      D2          -40

如果MaxMinusDoubleOfSecondToMax > 0那么我们只需要相应(实体,部门)组的最大记录,否则我们需要该组的所有记录。