SQL Server TSQL存储过程/查询速度慢

时间:2015-03-20 00:46:51

标签: sql sql-server database tsql report

我有一个SQL Server TSQL问题。我的存储过程正在运行 非常缓慢地。有关使用set操作改进这些查询的任何建议 非常感谢。

请记住,我无法控制数据的存储方式。

我有以下格式的两个表:

  1. 人员ID,姓名,DeletedFlag,SchedTotal,WorkedTotal,DeptNum,DeptName, [和这个问题的20个其他无关列]这是一个临时表 预填充了用户选择的人和用户 可以访问。

  2. 人物ID,RecordType,年份,HexMap

  3. 对于每个人,特定的记录将有两个或零 年。计划时间的一个记录和工作时间的一个记录。 hexmap 是一个字符串(每两个字符代表总计划或工作 时间)。我总是可以长达732个字符(每天一对) 从1月1日开始。我写了一个函数来分割字符串,所以我没有 担心这一点。

    结果通缉

    第一个表SchedTotal和WorkedTotal字段使用总计更新 从第二个表中根据用户选择的日期。日期 范围应在一个日历年内或跨越多个日历年。

    我可以做到,但我认为我采取了太多步骤。以下是什么 我现在正在做。建议表示赞赏:

    一个。 TEMP结果表1:对于用户范围内的每个日历年    选择的日期范围(While循环):插入临时表中    上表1所列人员的personid,recordtype和hexmap。

      WHILE (@YearCount <= @YearEnd)
       ....
      INSERT INTO #Tmp_HexMap (personid, hexMap, recordtype) 
      SELECT T1.personid, H.HexMap, H.recordtype 
      FROM [MyDatabase_' + CONVERT(Varchar(5),@DatabaseNum) + '].[dbo].[hextable] H 
      INNER JOIN #Tmp_Persons T1 ON T1.Personid = H.PersonID 
      WHERE Year = ' + CONVERT(Varchar(5),@YearCount)
    

    B中。 TEMP结果表2:仍然在每年的While循环中。一世    为每个人逐个计算行(内部循环)    并插入到另一个临时表中我的小数结果    hex spliter函数 - 它返回一个带小数的表变量    结果。我添加了personid,预定或工作日期和预定    和工作时间。

      WHILE (@PersonID IS NOT NULL)
       ....
      INSERT INTO #Tmp_scheduledtime (personid, scheddate, scheduledworkedtime) 
      SELECT @personid as personid, 
      DATEADD(dd,(Row_Number() OVER(Order by (Select NULL))+(@CurrentStartInt-1)-1),@YearStartDate) AS SchedDate, 
      workedtime FROM Report_Maint.dbo.workedtimesplit(@HexMap,@CurrentStartInt,@WorkedTimeDateINT) 
    

    ℃。 TEMP RESULT表3&amp; 4:在while循环之外,我将总计插入临时表:

     INSERT INTO #Tmp_Grouped1 (personid, ScheduledTotal, WorkedTotal)
     SELECT personid, ISNULL(SUM(scheduledworkedtime),-1.00) From #Tmp_scheduledtime
     GROUP BY personid
    

    d。最后,我更新了原始表:

        'UPDATE #Tmp_Persons ' +
        'SET HoursSched = ScheduledWorkedTotal ' +
        'From #Tmp_Grouped1 TG ' +
        'WHERE TG.Personid = #Tmp_Persons.Personid ' +
      '  AND #Tmp_persons.PeriodBegin >= ' + '''' + CONVERT(nvarchar(24),@DateBegin,121) + '''' + ' ' +
        'AND #Tmp_persons.PeriodEnd <= ' + '''' + CONVERT(nvarchar(24),@DateEnd,121) + ''''
    

    是否有任何想法将这些问题分成一个或两个查询而不是通过while循环? 谢谢你的帮助!

    标记

1 个答案:

答案 0 :(得分:0)

我的示例中没有足够具体的数据,但一般情况下,您可以使用JOIN执行基于集合的UPDATE,以实现此类行为,无需循环和快速性能。让我举一个简单的例子进行演示。

CREATE TABLE Products
(ProductID int
,Name varchar(30)
,Price money)

CREATE TABLE NewPrices
(ProductID int
,Price money)

为了帮助想象它,首先在它们之间写一个连接,以便并排查看新旧价格:

SELECT p.ProductID, p.Name, p.Price as OriginalPrice, n.Price as NewPrice
FROM Products as p
JOIN NewPrices as n on p.ProductID = n.ProductID

OK简单JOIN,你可以看到价格并排。现在只需将SELECT更改为UPDATE,但保持FROM和JOIN如下:

UPDATE p
SET Price = n.Price
FROM Products as p
JOIN NewPrices as n on p.ProductID = n.ProductID

这将匹配ProductID上的表中的每条记录,并更新p表中的值,即具有来自n表中匹配行的值的产品,即NewPrices。

基本上,FROM语句与C语言中的FOR语句相同,SELECT类似于PRINT语句。所以FROM&amp; JOIN正在执行WHILE语句的循环。您不是在执行SELECT,而是更新两个表的JOIN的每一行。

掌握了这一点后,请查看SQL Server中的MERGE语句,探索可以做些什么的魔术。