【问题标题】:Reducing an extensive Query减少广泛的查询
【发布时间】:2014-03-06 04:08:48
【问题描述】:

我正在从我们的数据库中编译有关工作票的历史数据。在过去的 12 个月中,我使用的是本月的最后一天。在那个日期,我想看看有多少张票是打开的(日期在一个月的最后一天之前或等于最后一天之前创建,最后一天之后的 dateclose 或 null)。截至当月最后一天,其中有多少张票已开放超过 30 天,以及该月有多少张票已关闭。

我的查询为过去 12 个月的每个月返回 4 个值。我开发了一个查询,一次收集一个月的数据,然后使用 Union 获取下一个月的数据,依此类推。

我现在正在尝试开发一个不需要为每个月收集的数据使用联合的查询。这是一个示例月份。

Select Convert(Varchar,
               DATEADD(day,
                       -1,
                       DATEADD(mm, DATEDIFF(m, 0, GETDATE()) - 12, 0)),
               101) as [ DateRun ],
       t1. [ data1 ],
       sum(t2. [ data2 ] + t3. [ data3 ]) as [ Total Open ],
       (t1. [ data1 ] + 0.0) /
       sum((t2. [ data2 ] + 0.0) + (t3. [ data3 ] + 0.0)) as [ Percent Aged Over 30 Days ]
  From (Select count(*) as [ data1 ]
          From (Select s.ticketnumber, s.datecreated, s.dateclosed
                  from mydb2 i
                 inner join mydb1 s
                    on i.ticketNumber = s.ticketNumber
                 Where datediff(dd,
                                s.dateCreated,
                                DATEADD(day,
                                        -1,
                                        DATEADD(mm,
                                                DATEDIFF(m, 0, GETDATE()) - 12,
                                                0))) > '30'
                   AND (s.dateclosed is null OR
                        s.dateclosed >=
                        DATEADD(day,
                                -1,
                                DATEADD(mm, DATEDIFF(m, 0, GETDATE()) - 12, 0)))
                 Group by s.ticketNumber, s.datecreated, s.dateclosed) as tb1) as t1,
       (Select count(*) as [ data2 ]
          From (Select s.ticketnumber, s.datecreated, s.dateclosed
                  from mydb2 i
                 inner join mydb1 s
                    on i.ticketNumber = s.ticketNumber
                 Where s.datecreated <
                       DATEADD(day,
                               -1,
                               DATEADD(mm, DATEDIFF(m, 0, GETDATE()) - 12, 0))
                   AND (s.dateclosed is null OR
                       s.dateclosed >=
                       DATEADD(day,
                                -1,
                                DATEADD(mm, DATEDIFF(m, 0, GETDATE()) - 12, 0)))
                 Group by s.ticketNumber, s.datecreated, s.dateclosed) as tb2) as t2,
       (Select count(*) as [ data3 ]
          From (Select s.ticketnumber, s.datecreated, s.dateclosed
                  from mydb2 i
                 inner join mydb1 s
                    on i.ticketNumber = s.ticketNumber
                 Where s.dateclosed >
                       DATEADD(day,
                               -1,
                               DATEADD(mm, DATEDIFF(m, 0, GETDATE()) - 13, 1))
                   AND s.dateclosed <
                       DATEADD(day,
                               -1,
                               DATEADD(mm, DATEDIFF(m, 0, GETDATE()) - 12, 0))
                 Group by s.ticketNumber, s.datecreated, s.dateclosed) as tb3) as t3
 Group by t1. [ data1 ]

通过研究,我能够在最后一天使用以下代码获得过去 12 个月,但我无法更新上面的代码,因此我不需要 12 个联合。

Select dateadd(month, 1 + datediff(month, 0, s.datecreated), -1) as [ Date Run ]
  from mydb1 s
 Where s.datecreated >
       DATEADD(day, -1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()) - 12, 0))
   and s.datecreated <
       DATEADD(day, -1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()), 0))
 Group by dateadd(month, 1 + datediff(month, 0, s.datecreated), -1)
 Order by 1

【问题讨论】:

  • 那个缩进结构让我生病了。
  • 我对缩进表示歉意(也让我发疯)。该查询是 MS Excel 外部 Microsoft 查询的一部分。它没有很好地复制和粘贴。

标签: sql date


【解决方案1】:

您可以尝试使用 CTE 生成月份,将其用作查询的基础,然后将聚合作为子查询运行。换句话说,是这样的:

with Months( ClosingDate, n ) as
(
    select DATEADD(dd, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)) as ClosingDate, 1 as n
    union all
    select DATEADD(dd, -1, DATEADD(mm, -1, DATEADD(dd, 1, ClosingDate))), n + 1
    from Months
    where n < 12
) 
select DATENAME(mm, m.ClosingDate) MonthLabel, DATEADD(dd, 1 - DATEPART(dd, m.ClosingDate), m.ClosingDate) OpeningDate, m.ClosingDate,
ISNULL((select COUNT(*)
    from mydb1 s
    where s.dateCreated < DATEADD(dd, -29, m.ClosingDate)
      and (s.dateClosed is null or s.dateClosed >= DATEADD(dd, 1, m.ClosingDate))
), 0) [Total Open 30+ Days]
from Months m

为清楚起见,我只包括了其中一个聚合,并省略了您的联接和分组。

【讨论】:

  • 此查询在 MS Excel 中作为外部 Microsoft Query。根据我的研究,使用 CTE 不起作用。你知道这是否是 MS Excel 中的一个选项吗?我能够得到我想要的数据,我只是希望我的查询比它更好。我也觉得这是新程序员可以学习的东西。
  • 如果您可以创建使用 CTE 的视图,则可以从 Microsoft Query 中引用该视图。或者,您可以从等式中删除 Microsoft Query,并使用比 ODBC 功能更丰富的驱动程序直接连接到数据库。根据您使用的数据库和驱动程序,you may also need to put a semicolon before the start of the CTE.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多