CREATE TABLE #SeqTbl (
        Seq int NOT NULL DEFAULT ( 0 ) ,
        C1 varchar( 10 ) NULL ,
        C2 varchar( 20 ) NULL ,
        UNIQUE ( C1 , C2 )
);
-- Sample data
INSERT INTO #SeqTbl ( C1 , C2 )
SELECT 'a' AS c1 , 'b' AS c2
UNION ALL
SELECT 'x' , 'y'
UNION ALL
SELECT '1' , NULL
UNION ALL
SELECT '*' AS c1 , '$' AS c2
UNION ALL
SELECT NULL , 'y'
UNION ALL
SELECT NULL , NULL;

SELECT * FROM #SeqTbl
/*
Seq         C1         C2                   
----------- ---------- -------------------- 
          0 a          b
          0 x          y
          0 1          NULL
          0 *          $
          0 NULL       y
          0 NULL       NULL
*/
GO
/*
        Objective: To sequence the rows in the order of C1 , C2. The
                   sequence numbers should match say a query with ORDER BY
                   clause of C1 , C2 viz: "SELECT * FROM tbl ORDER BY C1, C2".
        Solution : Concatenate the two columns & count the values 
                   less than or equal to a particular value.
                   The values should always be converted to fixed-length for
                   this logic to work. The CHAR(0) value for NULLs is used to
                   sort the NULL values on top. You can use a similar technique
                   to sort the NULL values at the bottom.
*/
-- Query that shows the concatenation results that will be used:
SELECT COALESCE( CONVERT( char( 10 ) , t1.C1 ) , REPLICATE( CHAR( 0 ) , 10 ) ) +
       COALESCE( CONVERT( char( 20 ) , t1.C2 ) , REPLICATE( CHAR( 0 ) , 20 ) ) AS OrderCols
FROM #SeqTbl AS t1
/*
OrderCols                      
------------------------------ 


*         $                   
1         
a         b                   
x         y                   
*/
UPDATE #SeqTbl
SET Seq =  ( SELECT COUNT( * ) FROM #SeqTbl AS t2
             WHERE COALESCE( CONVERT( char( 10 ) , t2.C1 ) , REPLICATE( CHAR( 0 ) , 10 ) ) +
                   COALESCE( CONVERT( char( 20 ) , t2.C2 ) , REPLICATE( CHAR( 0 ) , 20 ) )
                   <=
                   COALESCE( CONVERT( char( 10 ) , #SeqTbl.C1 ) , REPLICATE( CHAR( 0 ) , 10 ) ) +
                   COALESCE( CONVERT( char( 20 ) , #SeqTbl.C2 ) , REPLICATE( CHAR( 0 ) , 20 ) )
);
SELECT * FROM #SeqTbl
ORDER BY Seq;
/*
Seq         C1         C2                   
----------- ---------- -------------------- 
          1 NULL       NULL
          2 NULL       y
          3 *          $
          4 1          NULL
          5 a          b
          6 x          y
*/
GO
DROP TABLE #SeqTbl;
This page was last updated on May 01, 2006 04:28 PM.