home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.databases.ms-sqlserver      Notorious Rube Goldberg contraption      19,505 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 17,906 of 19,505   
   Erland Sommarskog to Jane TT   
   Re: FOR EACH type Statement in SQL Serve   
   09 Sep 10 23:21:22   
   
   From: esquel@sommarskog.se   
      
   Jane TT (janett@aol.com) writes:   
   > Hi, hope someone can help.  Although I have been using SQL for about 10   
   > years this problem has really got me stumped.   
   >   
   > I am using SQL Server 2000.   
   >   
   > I want to return the last five weeks data for each employee.  Not all   
   > employees are paid each week so I cannot call a set number of weeks.   
      
   We start with the (for the moment) useless advice:   
      
      WITH numbered AS (   
         SELECT empno, yeara, period, value,   
                rowno = row_number() OVER(PARTITION BY empno   
                                          ORDER BY yeara DESC, period DESC)   
      )   
      SELECT empno, yeara, period, value   
      FROM   tbl   
      WHERE  rn <=5   
      
   Or   
      
      SELECT a.empno, b.yeara, b.perioda, b.data   
      FROM   employees a   
      CROSS  APPLY (SELECT TOP 5 b.yeara, b.perioda, b.data   
                    FROM   employeedata b   
                    WHERE  a.empno = b.empno   
                    ORDER  BY b.yeard DESC, b.perioda DESC)   
      
   The reason that this is useless, is that both queries reqiures SQL 2005.   
      
   You can easily emulate row_number() on SQL 2000:   
      
      SELECT empno, yeara, period, value.   
      FROM   (SELECT a.empno, a.yeara, a.period, a.value,   
                      rowno = (SELECT COUNT(*)   
                               FROM   tbl b   
                               WHERE  b.empno = a.empno   
                                 AND  b.yeara <= a.yeara   
                                 AND  NOT (b.yeara = a.yeara AND   
                                           b.period > a.yeara))   
              FROM  tbl a) AS x   
      WHERE  rowno <= 5   
      
   There is a problem though: performance is likely to be if there is any   
   volume. And is not so much in terms of employees, but number of rows   
   per employeee.   
      
   One possibility is insert data into a temp table with an IDENTITY column,   
   and then use that for row number, and hope that ordering follows the   
   ORDER BY clause. It's someone uncertain whether you can rely on this on   
   SQL 2000. But here it goes:   
      
   INSERT #temp(empno, yeara, perioda, value)   
      SELECT empno, year, perioda, value   
      FROM   tbl   
      ORDER  BY empno, yeara, perioda   
      
   DELETE #temp   
   FROM   #temp a   
   WHERE  a.ident < (SELECT MAX(b.ident)   
                     FROM   #temp b   
                     WHERE  b.empno = a.empno)   
      
   #temp then has your data.   
      
   And when nothing else works, sigh, we can use a cursor.   
      
   DECLARE cur CURSOR STATIC LOCAL FOR   
      SELECT empno, year, perioda, value   
      FROM   tbl   
      ORDER  BY empno, yeara DESC, perioda DESC   
      
   OPEN cur   
      
   SELECT @rowno = 1, @old_empno = ''   
      
   WHILE 1 = 1   
   BEGIN   
      FETCH cur INTO @empno, @year, @perioda, @value   
      IF @@fetch_status <> 0   
         BREAK   
      
      IF @empno = @old_tempno   
      BEGIN   
         IF @rowno > 5   
            CONTINUE   
      
         INSERT #temp(empno, year, perioda, value)   
            VALUES (@empno, @year, @perioda, @value)   
      
         SELECT @rowno = @rowno + 1   
      END   
      ELSE   
         SELECT @rowno = 1, @old_empno = @empno   
   END   
      
   DEALLOCATE cur   
      
      
   Note: no code in this post is actually tested.   
      
   But the cursor above can be written smarter. Just loop over the employess   
   and run the TOP 5. But that is left as an exercise to the reader!   
      
      
      
      
   --   
   Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se   
      
   Links for SQL Server Books Online:   
   SQL 2008: http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx   
   SQL 2005: http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx   
   SQL 2000: http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca