如何使用不同的标准两次使用相同的列和sql中的一个公共列

use*_*846 2 sql sql-server sql-server-2008

我有一张桌子

ID  P_ID  Cost
1   101   1000
2   101   1050
3   101   1100
4   102   5000
5   102   2000
6   102   6000
7   103   3000
8   103   5000
9   103   4000
Run Code Online (Sandbox Code Playgroud)

我想使用"Cost"列两次来获取与我希望输出的每个P_ID相对应的成本中的第一个和最后一个插入值:

P_ID  First_Cost  Last_Cost
101    1000         1100
102    5000         6000
103    3000         4000
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 7

;WITH t AS 
(
  SELECT P_ID, Cost, 
    f = ROW_NUMBER() OVER (PARTITION BY P_ID ORDER BY ID),
    l = ROW_NUMBER() OVER (PARTITION BY P_ID ORDER BY ID DESC)
  FROM dbo.tablename
)
SELECT t.P_ID, t.Cost, t2.Cost
FROM t INNER JOIN t AS t2
ON t.P_ID = t2.P_ID
WHERE t.f = 1 AND t2.l = 1;
Run Code Online (Sandbox Code Playgroud)

在2012年,您将能够使用FIRST_VALUE():

SELECT DISTINCT
  P_ID, 
  FIRST_VALUE(Cost) OVER (PARTITION BY P_ID ORDER BY ID),
  FIRST_VALUE(Cost) OVER (PARTITION BY P_ID ORDER BY ID DESC)
FROM dbo.tablename;
Run Code Online (Sandbox Code Playgroud)

如果你删除了DISTINCT,而是使用ROW_NUMBER()相同的分区来消除多个相同的行,你会获得一个更有利的计划P_ID:

;WITH t AS
(
  SELECT
   P_ID, 
   f = FIRST_VALUE(Cost) OVER (PARTITION BY P_ID ORDER BY ID),
   l = FIRST_VALUE(Cost) OVER (PARTITION BY P_ID ORDER BY ID DESC),
   r = ROW_NUMBER() OVER (PARTITION BY P_ID ORDER BY ID)
  FROM dbo.tablename
)
SELECT P_ID, f, l FROM t WHERE r = 1;
Run Code Online (Sandbox Code Playgroud)

LAST_VALUE()你问,为什么不呢?好吧,它不会像你期望的那样工作.有关更多详细信息,请参阅文档下的注释.