-1

我有一个要设置的查询,它基本上会在第 1 列中列出所有星期天,然后在第 2 列中为每个日期列出所有在那个星期天“打开”的项目(第 1 列日期,实际上可能是一周中的一天,重要的是获得未清项目的每周快照)。例如

Date               open items
------------       ---------------
2013-10-13         1650
2013-10-06         1554
2013-09-29         1788
(cont down)

我的数据库记录了每个项目的 openDate 和 closedDate。因此,第 2 列需要类似:计算打开日期 <= 列 1 日期并且关闭日期为 NULL(项目仍然打开)或关闭日期 >= 列 1 日期的项目总数。

我希望你能帮忙。我认为这个查询超出了我目前有限的 SQL 能力的限制。

非常感谢机器人

4

1 回答 1

0

在 SQL Server 中,您可以执行以下操作

create procedure dbo.DoSummary(@startdate datetime, @enddate datetime, @dow int)
as 
set DateFIRST @dow;

with cte (date) as (
    select case
            when datepart(dw, @startdate) = 1 then @startdate
            else dateadd(d,8-datepart(dw, @startdate), @startdate)
            end as date
    union all
    select dateadd(d,7, date)
    from cte where dateadd(d,7,date) < @enddate
)
select 
    cte.date, count(items.opened) as [Open]
from 
    cte left outer join items on cte.date >= items.opened and cte.date < coalesce(items.closed, dateadd(d,1,cte.date))
    group by cte.date

然后你只需执行

dbo.DoSummary '2001-01-01','2001-07-01', 7 

执行。

最后一个参数@dow控制使用星期几,7 是星期日

更新由于 OP 无权创建存储过程,您可以简单地将函数体用作原始 Sql。我将给出一个使用 c# 中的 ADO 的示例。

using (var conn = new SqlConnection(connectionString)) {
   using (var cmd = conn.CreateCommand()) {
     cmd.CommandText = "set DateFIRST @dow; " +
                       "with cte (date) as ( " +
                       "select case " +
                       "when datepart(dw, @startdate) = 1 then @startdate "+
                       "else dateadd(d,8-datepart(dw, @startdate), @startdate) " +
                       "end as date " +
                       "union all " +
                       "select dateadd(d,7, date) " +
                       "from cte where dateadd(d,7,date) < @enddate " +
                       ") " +
                       "select cte.date, count(items.opened) as [Open] " +
                       "from cte " +
                       "left outer join items " +
                       "on cte.date >= items.opened " +
                       "and cte.date < coalesce(items.closed, dateadd(d,1,cte.date)) "+
                       "group by cte.date ";
    cmd.Parameters.AddWithValue("@startdate", new DateTime(2001,01,01));
    cmd.Parameters.AddWithValue("@enddate", new DateTime(2001,04,01));
    cmd.Parameters.AddWithValue("@dow", 7);
    using (var reader = cmd.ExecuteReader()) {
      while (reader.Read()) {
         // do somthing with data
      }
    }
  }
}
于 2013-10-14T13:56:03.657 回答