对A列求和,而不对B列求和,具体取决于C列-SQL Server

对A列求和,而不对B列求和,具体取决于C列-SQL Server,sql,sql-server,Sql,Sql Server,我正试图设计一种方法,总是对a列(单位)求和,有时对B列(价格)求和,这取决于C列(版本)的值,同时滚动到D列(产品)级别。我想用一个case-when语句,但我遇到的问题是对价格的依赖,这是一种分层系统。如果可用,我必须取当前版本的价格值,如果可用,则取最近版本的价格值,如果当前版本和最近版本都不可用,我需要取旧版本的价格值。层列表变为当前>最近>旧。现在数据在SQL Server中 另外,如果同一产品的两个更高版本的价格不同,则返回的价格应不同于最旧版本的价格。例如,如果同一产品的三行价格分

我正试图设计一种方法,总是对a列(单位)求和,有时对B列(价格)求和,这取决于C列(版本)的值,同时滚动到D列(产品)级别。我想用一个case-when语句,但我遇到的问题是对价格的依赖,这是一种分层系统。如果可用,我必须取当前版本的价格值,如果可用,则取最近版本的价格值,如果当前版本和最近版本都不可用,我需要取旧版本的价格值。层列表变为当前>最近>旧。现在数据在SQL Server中

另外,如果同一产品的两个更高版本的价格不同,则返回的价格应不同于最旧版本的价格。例如,如果同一产品的三行价格分别为50、50和10以及旧版本、新版本和新版本,则返回的价格将为10

因此,如果起始数据如下所示:

--------------------------------------------------
|  Units      |  Price  |  Version    | Product  |
--------------------------------------------------
|  105        |  50     |  Old        | Bear     |
--------------------------------------------------
|  100        |  100    |  Recent     | Bear     |
--------------------------------------------------
|  100        |  150    |  Current    | Bear     |
--------------------------------------------------
|  97         |  50     |  Old        | Bear     |
--------------------------------------------------
|  67         |  50     |  Old        | Goose    |
--------------------------------------------------
|  28         |  50     |  Recent     | Goose    |
--------------------------------------------------
|  10         |  10     |  Recent     | Goose    |
--------------------------------------------------
--------------------------------------------------
|  Units      |  Price  |  Version    | Product  |
--------------------------------------------------
|  402        |  150    |  Current    | Bear     |
--------------------------------------------------
|  105        |  10     |  Recent     | Goose    |
--------------------------------------------------
数据的汇总版本如下所示:

--------------------------------------------------
|  Units      |  Price  |  Version    | Product  |
--------------------------------------------------
|  105        |  50     |  Old        | Bear     |
--------------------------------------------------
|  100        |  100    |  Recent     | Bear     |
--------------------------------------------------
|  100        |  150    |  Current    | Bear     |
--------------------------------------------------
|  97         |  50     |  Old        | Bear     |
--------------------------------------------------
|  67         |  50     |  Old        | Goose    |
--------------------------------------------------
|  28         |  50     |  Recent     | Goose    |
--------------------------------------------------
|  10         |  10     |  Recent     | Goose    |
--------------------------------------------------
--------------------------------------------------
|  Units      |  Price  |  Version    | Product  |
--------------------------------------------------
|  402        |  150    |  Current    | Bear     |
--------------------------------------------------
|  105        |  10     |  Recent     | Goose    |
--------------------------------------------------

我是SQL新手,如果这是一个新手问题,我深表歉意。非常感谢您提供的任何帮助。

您可以使用条件聚合。诀窍是按优先级排序。一种方法使用
行号()
大小写

select sum(units) as units,
       max(case when seqnum = 1 then price end) as price,
       max(case when seqnum = 1 then version end) as version,
       product
from (select t.*,
             row_number() over (partition by product
                                order by (case version when 'old' then 3 when 'recent' then 2 when 'current' then 1 else 4 end)
                               ) as seqnum
      from t
     ) t
group by product;

另一个选项是将WITHTIES子句与Row_Number()配合使用

示例

Select Top 1 with ties 
       Units = sum(Units) over (Partition By Product)
      ,Price
      ,Version
      ,Product
 From  YourTable
 Order By Row_Number() over (Partition By Product Order by case when Version='Old' then 3 when Version='Recent' then 2 else 1 end)
返回

Units   Price   Version   Product
402     150     Current   Bear
95      10      Recent    Goose
Units   Price   Version Product
402     150     Current Bear
105     10      Recent  Goose
编辑-请求的更新

Select Top 1 with ties 
       Units = sum(Units) over (Partition By Product)
      ,Price
      ,Version
      ,Product
 From  YourTable
 Order By Row_Number() over (Partition By Product Order by case when Version='Old' then 3 when Version='Recent' then 2 else 1 end)
这里,我们使用CTE中的lag()函数来确定价格的变化

Declare @YourTable Table ([Units] int,[Price] int,[Version] varchar(50),[Product] varchar(50))
Insert Into @YourTable Values 
 (105,50,'Old','Bear')
,(100,100,'Recent','Bear')
,(100,150,'Current','Bear')
,(97,50,'Old','Bear')
,(67,50,'Old','Goose')
,(28,50,'Recent','Goose')
,(10,10,'Recent','Goose')

;with cte as (
Select Units = sum(Units) over (Partition By Product)
      ,Price
      ,Version
      ,Product
      ,PrevPrice = abs(Price-lag(Price,1) over (Partition By Product Order by case when Version='Old' then 3 when Version='Recent' then 2 else 1 end desc) )
 From  @YourTable
)
Select top 1 with ties
       Units 
      ,Price
      ,Version
      ,Product
 From  cte
 Order By Row_Number() over (Partition By Product Order by case when Version='Old' then 3 when Version='Recent' then 2 else 1 end ,PrevPrice desc) 
返回

Units   Price   Version   Product
402     150     Current   Bear
95      10      Recent    Goose
Units   Price   Version Product
402     150     Current Bear
105     10      Recent  Goose

很好的回答,这完美地解决了我的示例数据。我在实际数据中发现了一个复杂问题,即有两个不同的价格值都是“当前”的,我需要选择与“最近”价格值不同的值。我如何修改代码来处理这种情况?@user3347996。我建议你接受这个问题的答案,然后再问另一个问题,以合适的数据为例。谢谢John,这非常有帮助。我有一个和戈登一样的问题:我在实际数据中发现了一个复杂问题,即有两个不同的价格值都是“当前”的,我需要选择与“最近”价格值不同的值。我如何修改代码来处理这种情况?@user3347996如果您使用新的示例数据和所需的结果更新您的问题,也许可以。我相信lag()可以解决您的问题。谢谢John。我用新的样本数据更新了问题,并根据您的建议更改了所需的结果。@user3347996请参见编辑