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

时间:2014-01-21 20:21:48

标签: 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

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

P_ID  First_Cost  Last_Cost
101    1000         1100
102    5000         6000
103    3000         4000

4 个答案:

答案 0 :(得分: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;

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;

如果您删除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;

为什么不LAST_VALUE(),你问?好吧,它不会像你期望的那样工作。有关详细信息,请see the comments under the documentation

答案 1 :(得分:3)

SELECT t.P_ID, 
  SUM(CASE WHEN ID = t.minID THEN Cost ELSE 0 END) as FirstCost,
  SUM(CASE WHEN ID = t.maxID THEN Cost ELSE 0 END) as LastCost
FROM myTable
JOIN (
  SELECT P_ID, MIN(ID) as minID, MAX(ID) as maxID
  FROM myTable
  GROUP BY P_ID) t ON myTable.ID IN (t.minID, t.maxID)
GROUP BY t.P_ID

不可否认,@ AaronBertrand的方法在这里更清晰。但是,此解决方案适用于旧版本的SQL Server(不支持CTE或窗口功能),或几乎任何其他DBMS。

答案 2 :(得分:0)

你想要Min和Max的第一个和最后一个,或者你想要先输入哪一个以及最后输入哪一个?如果你想要Min和max,你可以分组。

SELECT P_ID,MIN(Cost),MAX(Cost)FROM table_name GROUP BY P_ID

答案 3 :(得分:0)

我相信这也是你的事情,只是没有自我加入或子查询:

SELECT DISTINCT
   P_ID
  ,MIN(Cost) OVER (PARTITION BY P_ID) as FirstCost
  ,MAX(Cost) OVER (PARTITION BY P_ID) as LastCost
FROM Table