2014-11-24 66 views
-5

我来完善这个查询,工作得非常好。提高SQL Server查询

DECLARE  @timTimeout int, 
     @iniDate varchar(20), 
     @endDate varchar(20)    
SET   @iniDate = '2014-07-20 00:00:00'    
SET   @endDate = '2014-11-24 23:59:59'   
SET   @timTimeout = 4000      

SET ANSI_WARNINGS OFF 

SELECT 
      'Approved (0200)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0200' THEN 1 END), 0), 
      'Approved Off (0220)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0220' THEN 1 END), 0), 
      'Cancel (0400)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0400' THEN 1 END), 0), 
      'Regret (0420)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0420' THEN 1 END), 0), 
      'TOTAL' = COUNT(*), 
      'Time-outs' = ISNULL(SUM(CASE WHEN DATEDIFF(ms, DateMsgIncome, DateMsgSent) > @timTimeout THEN 1 END), 0), 
      'Disponibility (%)' = (1 - CAST(ISNULL(SUM(CASE WHEN DATEDIFF(ms, DateMsgIncome, DateMsgSent) > @timTimeout THEN 1 END), 0) as money)/COUNT(*)) * 100 
FROM Message (NOLOCK) 
    WHERE DateMsgIncome BETWEEN @iniDate AND @endDate 
      AND CodMsgIncome IN ('0200', '0220', '0400', '0420', '0800', '0900', '9080', '9085') 
      AND DescMsgIncome <> '0220' 

现在,我必须准备一份总计数据按月组织的报告。

输出disered似乎是这样的:

 Approved (0200) | Approved Off (0220) | Cancel | Total | Time-outs | Disponibility (%) 
July | 35     15     12  62  0   100.00 
. 
. 
. 

编辑: 这是我的查询只有一个表。

Table Message: 
DateMsgIncome date, 
DateMsgSent date, 
CodMsgIncome varchar(4), 
DescMsgIncome varchar(4), 
CodMsgAnswer int. 

任何建议是值得欢迎的。 在此先感谢。

+2

你没有得到任何错误,是吗?您想以何种方式改进该查询?速度,美观,还是什么? – DrCopyPaste 2014-11-24 15:51:23

+0

嗯,我不知道如何按月分组数据。这是我想要的改进。 – TioDavid 2014-11-24 15:52:27

+2

它含糊不清,因为你没有描述你有什么表格结构。我们应该如何知道如何按月分组这个月份,当时我们甚至不知道该月份选择哪一列? (DateMsgIncome,DateMsgSent例如似乎是两个日期时间列) – DrCopyPaste 2014-11-24 15:58:06

回答

2

我跑查询通过代码格式化,以帮助它清理干净。我也改变了变量声明,因为你似乎不明白我在说什么。对于记录来说,您对它进行编码的方式可能会错过一天中最后几毫秒的某些行。

我改变了DATEDIFF函数使用阐明的日期部分的名称,因为它太容易使用错误的缩写,搞错了。我还简化了最后一栏的计算。如果将1更改为1.0,则不需要投钱。您应该避免使用保留字作为对象名称,并避免列名中出现空格。让前端做这种漂亮的格式化。

我还添加了使用不久表提示时,可以与关键字所需。 (我建议在使用之前理解NOLOCK的真正含义)。

DECLARE @timTimeout int 
    , @iniDate date 
    , @endDate date 

SET @iniDate = '2014-07-20'    
SET @endDate = '2014-11-25'   
SET @timTimeout = 4000      

SELECT MONTH(DateMsgIncome) as MyMonthColumn 
    , 'Approved (0200)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0200' THEN 1 END), 0) 
    , 'Approved Off (0220)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0220' THEN 1 END), 0) 
    , 'Cancel (0400)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0400' THEN 1 END), 0) 
    , 'Regret (0420)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0420' THEN 1 END), 0) 
    , 'TOTAL' = COUNT(*) 
    , 'Time-outs' = ISNULL(SUM(CASE WHEN DATEDIFF(MILLISECOND, DateMsgIncome, DateMsgSent) > @timTimeout THEN 1 END), 0) 
    , 'Disponibility (%)' = (1.0 - ISNULL(SUM(CASE WHEN DATEDIFF(MILLISECOND, DateMsgIncome, DateMsgSent) > @timTimeout THEN 1 END), 0)/COUNT(*)) * 100 
FROM [Message] WITH (NOLOCK) --Ack!!! I wouldn't let this fly on my system due to inconsistencies with this hint unless accuracy is not important (like 

WHERE DateMsgIncome >= @iniDate 
    AND DateMsgIncome < @endDate 
    AND CodMsgIncome IN 
    (
     '0200' 
     , '0220' 
     , '0400' 
     , '0420' 
     , '0800' 
     , '0900' 
     , '9080' 
     , '9085' 
    ) 
    AND DescMsgIncome <> '0220' 
GROUP BY MONTH(DateMsgIncome) 
+0

它是一个非常必要的表格,我必须防止锁定它。这就是其上的一个'nolock'的原因。我会测试你的答案。感谢您的帮助。 – TioDavid 2014-11-24 16:45:37

+0

我知道你不想锁定它。我经常会看到这种提示,用户并没有真正了解它在做什么。它可以并将会丢失和/或重复的行。 http://blogs.msdn.com/b/davidlean/archive/2009/04/06/sql-server-nolock-hint-other-poor-ideas.aspx – 2014-11-24 16:50:24

+0

它的工作就像我需要的一样。我只在'where'子句后面调整'group by'。感谢您的帮助和耐心。我不擅长SQL,但现在,我是唯一一个在这里做这个报告的人。再次感谢你。 – TioDavid 2014-11-24 16:57:14