【问题标题】:Recreate Moving Median and Moving Mode Excel formula in SQL在 SQL 中重新创建移动中位数和移动模式 Excel 公式
【发布时间】:2021-01-06 09:30:18
【问题描述】:

我正在尝试重新创建下面的 Excel 公式/表格并显示真/假但卡住了。

Excel 公式:=ABS(ROUND(MEDIAN(C$2:C2),0)-ROUND(MODE.SNGL(C$2:C2),0))

我有 200 多行数据,我只需要从第一行到当前行计算的中位数和众数。我可以为 SQL 中的所有行创建中位数,但这不符合我的需要。与模式相同。上面的公式将在 Excel 单元格 D2 中并向下填充。它在公式末尾调用的变量只是数字 4

任何建议或指示都会很棒。谢谢!

Excel sn-p: Quick view of how this table looks in Excel

用 SQL 构建这个精确表的 SQL 代码。

    IF NOT EXISTS (
    select * from sysobjects where name='SampleExample' and xtype='U'
) CREATE TABLE SampleExample (
    [Seconds] INT,
    [Sequence] INT,
    [Value] NUMERIC(12, 9),
    [Result] NVARCHAR(4)
);
INSERT INTO SampleExample VALUES
    (598,1,236.888453364,N'#N/A'),
    (740,2,236.888453364,N'True'),
    (885,3,235.463708639,N'True'),
    (1024,4,236.177295446,N'True'),
    (1189,5,236.177295446,N'True'),
    (1330,6,236.866638064,N'True'),
    (1463,7,236.177295446,N'True'),
    (1599,8,236.866638064,N'True'),
    (1735,9,236.866638064,N'True'),
    (1863,10,236.866638064,N'True'),
    (1986,11,236.866638064,N'True'),
    (2110,12,236.866638064,N'True'),
    (2235,13,236.880749464,N'True'),
    (2362,14,236.908763647,N'True'),
    (2487,15,236.908763647,N'True'),
    (2610,16,236.908763647,N'True'),
    (2739,17,237.190827727,N'True'),
    (2865,18,237.190827727,N'True'),
    (3008,19,237.190827727,N'True'),
    (3132,20,237.190827727,N'True');

当前中值查询。我在我的 SQL 表中添加了一个名为 Filename 的列,该列对于所有行都是相同的值。但这会找到平板电脑中所有行的中位数,而不是从第 1 行到当前行。

Declare @Median AS INT
Select @Median = ( 
    (Select MAX([Value])
    FROM 
        (Select TOP 50 PERCENT [Value], [Filename] 
        FROM SampleExample 
        
        Order by [Filename]) as BOTTOMHALF)
    + 
    (Select MIN([Value])
    FROM
        (Select TOP 50 PERCENT [Value], [Filename]
        FROM SampleExample 
        
        Order by [Filename] desc) as TOPHALF) ) / 2 

当前模式查询:

Declare @Mode as INT
Select @Mode = (
    Select TOP 1 ROUND([Value],0) as MODE
    from SampleExample 
    Group by [Value]
    Order by COUNT(*) DESC
    )

我正在寻找的结果是真/假。我在我的 SQL 查询中使用 CASE:

CASE WHEN @Variable > @Median - @Mode THEN 'True' ELSE 'False' END AS Result

【问题讨论】:

  • 请标记您的数据库。
  • 请展示您为获取中位数和众数而准备的 SQL。
  • 这也有助于显示来自上述数据集的预期结果(例如,来自您的 Excel 版本)。
  • 我已在原始帖子中添加了这些附加详细信息。谢谢。

标签: sql sql-server excel database median


【解决方案1】:

SQL Server(以及一般的 SQL)具有计算中位数的功能。它具有直观的名称percentile_cont()。而且,它只是作为窗口函数存在,而不是聚合函数。

你想要一个连续的中位数。理想情况下,这样写会很好:

select se.*,
       avg(value) over (order by sequence) as avg_value,
       percentile_cont(0.5) over (within group order by sequence) over (order by sequence)
from sampleexample se;

但不支持累积中位数。所以,剩下的 apply 选项:

select se.*, se2.*
from sampleexample se cross apply
     (select top (1)  percentile_cont(0.5) within group (order by value) over () as median,
             avg(value) over () as avg_value
      from sampleexample se2
      where se2.sequence <= se.sequence
     ) se2;

Here 是一个 dbfiddle。

编辑:

我真的把这个问题理解为中位数和平均值,而不是中位数和众数(我的愿望是阅读)。对于该模式,您确实需要一个子查询,所以:

select se.*, se2.*
from sesampleexample se cross apply
     (select top (1) percentile_cont(0.5) within group (order by value) over () as median,
             avg(value) over () as avg_value,
             value as mode
      from (select se2.*, count(*) over (partition by se2.value) as value_cnt
            from sampleexample se2
            where se2.sequence <= se.sequence
           ) se2
      order by se2.value_cnt desc
     ) se2

【讨论】:

  • 感谢您的启发性示例。我是一个 DB2 用户,直到现在才将 CROSS APPLY 视为 SQL Server 的 LATERAL JOIN 等效项。我也没有意识到当你必须提供它但不想要 PARTITION BY 时你可以使用一个空的 OVER() 子句。因此,一个示例中有 2 节课。太好了!
  • 顺便说一句,您的答案似乎计算了平均值而不是众数?
  • 您是否忽略了为模式添加子查询?我不得不用(SELECT TOP 1 value FROM SampleExample WHERE sequence &lt;= se.sequence GROUP BY value ORDER BY COUNT(*) DESC, value) AS mode 替换您查询中的value as mode 以获得预期的输出。
  • value as mode 似乎没有给出正确的模式结果。 (我使用 Google 表格检查了示例数据)。
  • @user9601310 。 . .我修改了代码并添加了 dbfiddle。以前的版本中有一些“一厢情愿的编程”。逻辑现在应该可以工作了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
  • 1970-01-01
  • 1970-01-01
  • 2017-04-19
  • 1970-01-01
相关资源
最近更新 更多