【问题标题】:Finding Median between TWO dates SQL Server 2008查找两个日期之间的中位数 SQL Server 2008
【发布时间】:2015-02-13 21:10:32
【问题描述】:

我正在寻找一种方法来获取一堆开始日期和结束日期(很多和很多日期)的中位数。但是,它将特定于各种“发票编号”。请参阅下面的示例数据。

 invoice_no    invoice start date      invoice end date
 4006            11/14/2001               12/15/2004
 20071           11/29/2001               02/01/2003
 19893           11/30/2001               12/02/2001
 19894           11/30/2001               12/04/2001
 004             10/22/2002               10/31/2002
 004             12/02/2002               10/31/2002
 004             01/19/2002               10/31/2002
 004             05/10/2002               10/31/2002

求开始日期和结束日期之间的中位数。

对于只显示一次的发票,中位数将是该特定 invoice_no 的开始日期和结束日期之间的任何值。但是,许多情况下会显示发票“004”。它会在不同的日期重复很多次——但这里的概念仍然相同。需要找到两个日期之间的中位数,但仍需要根据该发票编号显示。

尽可能过滤数据。我意识到我也可以做 WHERE STATUS 'REJECTED' 并且它也应该有助于避免很多不必要的日期。另外,我只想在几个月之间过滤,所以我也添加了 BETWEEN DATETIME。

到目前为止的代码(但不工作......如果有 1 个日期列,这种逻辑似乎工作,但现在我们正在处理两个日期,所以我不确定):

 与
          时间间隔
    (
        选择发票编号,
        invoice_start_date、invoice_end_date、check_date、status_code、
        cast(count(*) OVER (PARTITION BY invoice_no) as float) 总计,
        row_number() OVER (PARTITION BY invoice_no ORDER BY
        invoice_start_date, invoice_end_date, check_date) AS rn

    FROM    INVOICE_HEADER INNER JOIN
   INVOICE_HEADER_CUSTOM ON INVOICE_HEADER.invoice_id 
    = INVOICE_HEADER_CUSTOM.invoice_id

    WHERE status_code <> 'REJECTED' AND 
    Check_Date BETWEEN CONVERT(DATETIME, '2014-12-01 00:00:00', 102) 
    AND CONVERT(DATETIME, '2014-12-31 00:00:00', 102)
)

    SELECT *
    FROM tmp
    WHERE (total / 2.0 - 1) < rn and rn < (total / 2.0 + 1) 

【问题讨论】:

    标签: sql sql-server-2008 date median


    【解决方案1】:

    如果您指的是开始日期和结束日期的集合,则将它们放在一列中:

    WITH t AS (
           SELECT invoice_no, invoice_start_date, invoice_end_date, check_date, status_code,
           FROM INVOICE_HEADER INNER JOIN
                INVOICE_HEADER_CUSTOM
                ON INVOICE_HEADER.invoice_id = INVOICE_HEADER_CUSTOM.invoice_id
           WHERE status_code <> 'REJECTED' AND 
                 Check_Date BETWEEN CONVERT(DATETIME, '2014-12-01 00:00:00', 102) AND
                 CONVERT(DATETIME, '2014-12-31 00:00:00', 102)
         ), 
         t2 as (
          select d, row_number() over (order by d) as seqnum,
                 count(*) over () as cnt
          from (select invoice_start_date as d from t
                union all
                select invoice_end_date as d from t
               ) t
         )
    select dateadd(day, datediff(hour, min(d), max(d)) / 2.0, min(d))
    from t2
    where 2 * seqnum in (cnt, cnt + 1, cnt + 2);
    

    【讨论】:

      【解决方案2】:

      好的...试试this page上的查询:

      SELECT @Median = AVG(1.0 * val)
      FROM 
      (
        SELECT val, 
           c  = COUNT(*) OVER (),
           rn = ROW_NUMBER() OVER (ORDER BY val)
        FROM dbo.EvenRows
      ) AS x
      WHERE rn IN ((c + 1)/2, (c + 2)/2);
      

      【讨论】:

      • 如果有 1 列日期,这似乎是一个可行的逻辑。没有?
      • median 只为一系列数字定义,而不是多个维度。
      • 是的——但是有一个开始日期和一个结束日期是“一系列数字”,不是吗?它仍然是同一平面上的日期,只是存储在不同的列中。这就是你所说的“维度”吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-15
      • 2015-02-11
      • 1970-01-01
      • 2015-03-11
      • 1970-01-01
      • 2018-07-25
      • 1970-01-01
      相关资源
      最近更新 更多