Search code examples
sqlsql-servercursordynamic-sql

Result set in column not row


I need to get the minimum values for 16 columns at a time.

I.e. 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16

minimum= 1

I need this to slid over 1 ever for a new set of 16 and get the minium values for that one as well

i.e. 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17

Minimum 2

There are 2571 columns with 11,000 rows.

So far I am getting the rows from:

DECLARE @Start INT =1 
DECLARE @End INT=16 
Begin Transaction
SELECT * 
FROM   (SELECT Row=Row_number() 
                     OVER ( 
                       ORDER BY column_name), 
               column_name 
        FROM   information_schema.columns 
        WHERE  table_name IN ( '100', '200', '300', '400' ) 
               AND column_name NOT IN ( 'time', 'scan' ))Row 
WHERE  row >= @start 
       AND row <= @end 
Commit

This is giving me the first 16 columns but in a column. I would like to open this up and put the returning results into a cursor where i can execute it for row by row analysis.

Something like this, Though if I add 1 to the row number for each one I want it should move it over.

DECLARE @Column01 NVARCHAR(50), 
        @Column02 NVARCHAR(50), 
        @Column03 NVARCHAR(50), 
        @Column04 NVARCHAR(50), 
        @Column05 NVARCHAR(50), 
        @Column06 NVARCHAR(50), 
        @Column07 NVARCHAR(50), 
        @Column08 NVARCHAR(50), 
        @Column09 NVARCHAR(50), 
        @Column10 NVARCHAR(50), 
        @Column11 NVARCHAR(50), 
        @Column12 NVARCHAR(50), 
        @Column13 NVARCHAR(50), 
        @Column14 NVARCHAR(50), 
        @Column15 NVARCHAR(50), 
        @Column16 NVARCHAR(50) 

DECLARE @Start INT =1 
DECLARE @End INT=16 


DECLARE db_cursor CURSOR FOR 
  SELECT column_name 
  FROM   (SELECT Row=Row_number() 
                       OVER ( 
                         ORDER BY column_name), 
                 column_name 
          FROM   information_schema.columns 
          WHERE  table_name IN ( '100', '200', '300', '400' ) 
                 AND column_name NOT IN ( 'time', 'scan' ))Row 
  WHERE  row >= @start
         AND row <= @end 

OPEN db_cursor  
FETCH NEXT FROM db_cursor INTO  @Column01 ,@Column02

WHILE @@FETCH_STATUS = 0  
BEGIN  

      --do work here    
      print @Column01 + ' ' + @Column02

    FETCH NEXT FROM db_cursor INTO  @Column01 , 
@Column02 
END  

CLOSE db_cursor  
DEALLOCATE db_cursor

I know I can pivot it but would that work for what i want since i do not need an aggregate? Any suggestions?


Solution

  • You don't need dynamic sql. Just normalize your data with an UNPIVOT.

    WITH t AS (
      SELECT row, scan, col, val
      FROM MyTable
      UNPIVOT(val FOR col IN ([1],[2],[3],[4],...<snip>...,[2570],[2571]))p
    )
    SELECT
      row, scan, col AS range_start, col + 15 AS range_end, min_val
    FROM t t1
    CROSS APPLY (
      SELECT
        MIN(t2.val) AS min_val
      FROM t
      WHERE
        row = t1.row AND
        scan = t1.scan AND
        col BETWEEN t1.col AND t1.col + 15
    ) t2