【问题标题】:How to calculate the slope in SQL如何在 SQL 中计算斜率
【发布时间】:2012-02-23 11:31:29
【问题描述】:

我在 sql 数据库中有一些数据,我想计算斜率。数据有这样的布局:

Date        |  Keyword  |  Score    
2012-01-10  |  ipad     |  0.12    
2012-01-11  |  ipad     |  0.17    
2012-01-12  |  ipad     |  0.24    
2012-01-10  |  taco     |  0.19    
2012-01-11  |  taco     |  0.34    
2012-01-12  |  taco     |  0.45    

我希望通过使用 SQL 创建一个新表,最终输出看起来像这样:

Date        |  Keyword  |  Score |  Slope    
2012-01-10  |  ipad     |  0.12  |  0.06    
2012-01-11  |  ipad     |  0.17  |  0.06    
2012-01-12  |  ipad     |  0.24  |  0.06    
2012-01-10  |  taco     |  0.19  |  0.13    
2012-01-11  |  taco     |  0.34  |  0.13    
2012-01-12  |  taco     |  0.45  |  0.13

更复杂的是,并非所有关键字都有 3 个日期的数据,例如有些只有 2 个。

SQL 越简单越好,因为我的数据库是专有的,我不太确定有哪些公式可用,尽管我知道如果有帮助的话它可以做 OVER(PARTITION BY)。谢谢!

更新:我将斜率定义为最适合 y=mx+p 在 excel 中也就是 =slope()

这是我通常在 excel 中操作的另一个实际示例:

date        keyword         score       slope   
1/22/2012   water bottle    0.010885442 0.000334784  
1/23/2012   water bottle    0.011203949 0.000334784  
1/24/2012   water bottle    0.008460835 0.000334784  
1/25/2012   water bottle    0.010363991 0.000334784  
1/26/2012   water bottle    0.011800716 0.000334784  
1/27/2012   water bottle    0.012948411 0.000334784  
1/28/2012   water bottle    0.012732459 0.000334784  
1/29/2012   water bottle    0.011682568 0.000334784  

【问题讨论】:

  • 看看这个关于 SQL 中线性回归的问题。 stackoverflow.com/questions/2536895/…
  • @datayoda - 你如何定义斜率?如果您有两个以上的数据点,您是否只是从最早点到最新点的斜率?还是您想在所有点之间画一条最佳拟合线?如果是这样,使用线性最小二乘法或其他算法?您是否要强制直线达到某一点(知道这会降低整体拟合优度)?
  • Oracle中有一些线性回归函数。 docs.oracle.com/cd/B10501_01/server.920/a96540/…
  • 我没有可用的 regr_slope :(
  • @NWest 是正确的,你需要使用线性回归,他的第一个链接似乎相当不错。一个简单的y = mx + c 不会像您的数据点那样起作用,并且极不可能形成完美的“曲线”。还要记住,只有 2-3 个数据点,你的曲线无论如何都会相当不准确。

标签: mysql sql oracle10g


【解决方案1】:

如果您将斜率定义为从最早点到最新点的斜率,并且如果分数仅随日期增加,那么您可以通过以下方式获得上面的输出:

SELECT *
  FROM scores
  JOIN
    (SELECT foo.keyword,
            (MAX(score)-MIN(score)) / DATEDIFF(MAX(date),MIN(date)) AS score
     FROM scores
     GROUP BY keyword) a
  USING(keyword);

但是,如果您想要线性回归,或者分数会随着时间的推移而降低和增加,您将需要更复杂的东西。

【讨论】:

  • 分数也会降低,我的意思是最适合的坡度
【解决方案2】:

我能做的最干净的一个:

SELECT
    Scores.Date, Scores.Keyword, Scores.Score,
    (N * Sum_XY - Sum_X * Sum_Y)/(N * Sum_X2 - Sum_X * Sum_X) AS Slope
FROM Scores
INNER JOIN (
    SELECT
        Keyword,
        COUNT(*) AS N,
        SUM(CAST(Date as float)) AS Sum_X,
        SUM(CAST(Date as float) * CAST(Date as float)) AS Sum_X2,
        SUM(Score) AS Sum_Y,
        SUM(CAST(Date as float) * Score) AS Sum_XY
    FROM Scores
    GROUP BY Keyword
) G ON G.Keyword = Scores.Keyword;

它使用Simple Linear Regression 计算斜率。

结果:

Date         Keyword        Score         Slope
2012-01-22   water bottle   0,010885442   0,000334784345222076
2012-01-23   water bottle   0,011203949   0,000334784345222076
2012-01-24   water bottle   0,008460835   0,000334784345222076
2012-01-25   water bottle   0,010363991   0,000334784345222076
2012-01-26   water bottle   0,011800716   0,000334784345222076
2012-01-27   water bottle   0,012948411   0,000334784345222076
2012-01-28   water bottle   0,012732459   0,000334784345222076
2012-01-29   water bottle   0,011682568   0,000334784345222076

每个数据库系统似乎都有不同的方法将日期转换为数字:

  • MySQL: TO_SECONDS(date)TO_DAYS(date)
  • 甲骨文: TO_NUMBER(TO_CHAR(date, 'J'))date - TO_DATE('1','yyyy')
  • MS SQL Server: CAST(date AS float)(或等效的CONVERT

【讨论】:

  • @arielhasidim 是的。我删除了它。它仅用于计算置信区间和相关系数。这超出了问题的范围。
【解决方案3】:

转换为十进制对我来说没有给出正确的结果,它与日期不是线性的。请改用TO_DAYS(date_field),这将是正确的。

【讨论】:

    【解决方案4】:

    使用这个

    SUM(CONVERT(float, datediff(dd, '1/1/1900', date_field)))
    

    而不是

    SUM(CAST(date_field AS float))
    

    【讨论】:

    • 请正确格式化您的代码,以便更好地理解您的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 2016-06-07
    • 2017-05-02
    相关资源
    最近更新 更多