【问题标题】:SQL - Calculating third column from previous twoSQL - 从前两列计算第三列
【发布时间】:2019-06-17 17:26:23
【问题描述】:

我刚开始使用SQL,在用这种语言思考方面有些困难。

我现在有一个任务,我需要在表中创建一个新列,其中包含以前列的值。此计算基于少数几个条件。这甚至可以在 SQL 中轻松完成吗?

假设我有一个名为 dbo.country_sales 的表

Select *
From dbo.country

生成

CountryName, Year, Sales
—————————
Argentina, 2015, 10
Argentina, 2017, 22
Florida, 2015, 10
Florida, 2017, 8
Germany, 2015, null
Germany, 2017, null

我需要创建 2015 年至 2017 年之间的销售发展情况的第四列(2017 年的销售额 - 2015 年的销售额),因此表格如下所示:

CountryName, Year, Sales, Development
—————————
Argentina, 2015, 10, 12
Argentina, 2017, 22, 12
Florida, 2015, 10, -2
Florida, 2017, 8, -2
Germany, 2015, null, null
Germany, 2017, null, null

我知道如何在 select 语句中创建它,但它只计算 1 个值。尝试搜索了几个小时,但没有找到任何简单的东西。

感谢您的帮助。 局域网

【问题讨论】:

  • 顺便说一句,佛罗里达州不是一个国家,我最后一次检查 ;)
  • 您是否打算在阿根廷 2015 发展中获得 12 的值?还是您真的只希望在 2017 年的记录中使用它?
  • 实际上我会计算 CAGR,但这只是一个例子。复合年增长率仅对选定时期的最后一年有意义。我可以在最后几年以外的其他年份输入相同的 CAGR 或 null。

标签: sql sql-server conditional-statements calculated-columns


【解决方案1】:

一种简单的方法使用窗口函数和条件聚合:

select c.*,
       sum(case when year = 2017 then sales
                when year = 2015 then - sales
           end) over (partition by country) as diff_2017_2015
from dbo.country c
where year in (2015, 2017);

【讨论】:

  • 是的,这个查询比我的要短。
【解决方案2】:

您可以使用 CTE 预先计算值。例如:

with a as (
  select countryname, year, sales from t where year = 2015
),
b as (
  select countryname, year, sales from t where year = 2017
),
c as (
  select a.countryname, b.sales - a.sales as development
  from a
  join b on a.countryname = b.countryname
)
select a.*, c.development
from a
join c on c.countryname = a.countryname
union 
select b.*, c.development
from b
join c on c.countryname = b.countryname
order by countryname, year

【讨论】:

  • 感谢这个。我需要通过POWER 进行一些 CAGR 计算,所以这比第一个建议的解决方案要好一些。不幸的是,这需要更多时间,因为我猜是加入。
【解决方案3】:

对于可能为您提供更多灵活性以供将来使用的稍微更奇特的解决方案,您可以创建一个辅助函数。

CREATE FUNCTION dbo.udf_SalesDiff(
  @CountryName  VARCHAR(50)
 ,@LookbackYear INT
 ,@CurrentSales MONEY
)
RETURNS MONEY
BEGIN

  DECLARE @Diff MONEY

  SELECT @Diff = @CurrentSales - [Sales]
  FROM dbo.CountrySales
  WHERE [CountryName] = @CountryName AND [Year] = @LookbackYear

  RETURN @Diff

END

你可以在哪里使用它:

SELECT 
  [CountryName]
 ,[Year]
 ,dbo.udf_SalesDiff([CountryName],2015,[Sales]) AS Development
FROM dbo.CountrySales
WHERE [Year]=2017

并将产生:

CountryName | Year | Development
--------------------------------
Argentina   | 2017 | 12
Florida     | 2017 | -2
Germany     | 2017 | NULL

【讨论】:

  • 我的假设是这些记录在 CountryName 和 Year 上是唯一的。为确保,我还推荐CREATE UNIQUE INDEX uidx_CountrySales ON dbo.CountrySales(CountryName,Year) 否则,您必须在函数中使用 SUM 和基本查询进行聚合。
猜你喜欢
  • 2020-08-11
  • 1970-01-01
  • 2012-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多