Home > Net >  Formatting query results in t-sql
Formatting query results in t-sql

Time:12-13

This is my current code that generate 2 multiplication tables starting from a given number:

CREATE
    OR

ALTER PROCEDURE dbo.math_tables (@x INT = 1)
AS
BEGIN
    DECLARE @y INT = 1
    DECLARE @ctr INT = 0

    BEGIN
        WHILE @ctr <= 2
        BEGIN
            WHILE @y <= 10
            BEGIN
                 PRINT ltrim(str(@x))   ' x '   ltrim(str(@y))   ' = '   ltrim(str(@x * @y))

                SET @y  = 1
            END

            SET @x  = 1
            SET @y = 1
            SET @ctr  = 1

            PRINT '---------------------------'
        END
    END
END
GO

EXECUTE dbo.math_tables 5 /* Starting table */
GO

The results currently look like this one after the other:

5 x 1 = 5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
5 x 6 = 30
5 x 7 = 35
5 x 8 = 40
5 x 9 = 45
5 x 10 = 50
---------------------------
6 x 1 = 6
6 x 2 = 12
6 x 3 = 18
6 x 4 = 24
6 x 5 = 30
6 x 6 = 36
6 x 7 = 42
6 x 8 = 48
6 x 9 = 54
6 x 10 = 60
---------------------------

But I want it to look like this. Basically I'm trying to start from a new column every-time @ctr goes up by one:

5 x 1 = 5      6 x 1 = 6
5 x 2 = 10     6 x 2 = 12
5 x 3 = 15     6 x 3 = 18
5 x 4 = 20     6 x 4 = 24
5 x 5 = 25     6 x 5 = 30
5 x 6 = 30     6 x 6 = 36
5 x 7 = 35     6 x 7 = 42
5 x 8 = 40     6 x 8 = 48
5 x 9 = 45     6 x 9 = 54
5 x 10 = 50    6 x 10 = 60

Please don't ask why... I'm trynna learn query result formatting for readability ;D

CodePudding user response:

As per your requirement, you need to go with Temp/physical table. Choose whatever you can choose it. else you need to write some string manipulation operations more as per your result set.

I've modified the query as per my understanding. and confirm that I'm going with table approaches.

    DECLARE @x INT = 5
    DECLARE @y INT = 1
    DECLARE @ctr INT = 0
    DECLARE @Value NVARCHAR(200)
    DECLARE @SQL NVARCHAR(MAX)
    CREATE Table #Matrix
    (
        Id INT IDENTITY(1,1)
    )
    BEGIN
        WHILE @ctr <= 2     
        BEGIN
            EXEC('ALTER TABLE #Matrix ADD COL_' @ctr ' NVARCHAR(200)')
            WHILE @y <= 10
            BEGIN
                 SET @Value = ltrim(str(@x))   ' x '   ltrim(str(@y))   ' = '   ltrim(str(@x * @y))
                 IF(@ctr>0)
                 BEGIN
                    SET @SQL = CONCAT('UPDATE #Matrix SET [COL_',CAST(@ctr AS NVARCHAR),']=''',@Value,''' WHERE Id = ',@y)
                 END
                 ELSE
                 BEGIN
                    SET @SQL = CONCAT('INSERT INTO #Matrix([COL_',CAST(@ctr AS NVARCHAR),']) VALUES(''',@Value,''')')
                 END                 
                 EXEC(@SQL)
                SET @y  = 1
            END

            SET @x  = 1
            SET @y = 1
            SET @ctr  = 1
            
        END
    END
    SELECT * FROM #Matrix
    DROP TABLE #Matrix

Output

enter image description here

In the query, I added one table namely #Matrix In the table, we are adding the columns once while the loop executing.

Once a column is added to the table we insert/update the data into a table.

CodePudding user response:

As @Lamu suggested, here's a way to do it without loops or recursion. In 2022, you can replace the "Tally" cte with GENERATE_SERIES() or, if you have one, you can use you a Numbers/Tally table or set based function like Itzik Ben-Gan's "GetNums" function or my "fnTally" function.

And, a little integer division and Modulo do the "positioning" of the data. Remember that Modulus returns the "Remainder" for division and that when both the Dividend and the Divisor are integers, so will be the Quotient and the Remainder.

   WITH
cteTally AS
(--==== Generate a psuedo Tally Table from 1 to 11.
     -- We'll have a separating bar show up at 11.
 SELECT TOP (11)
        N = ROW_NUMBER() OVER (ORDER BY @@SPID) --Used for both the Multiplicand and Multiplier
   FROM      sys.all_columns ac1
  CROSS JOIN sys.all_columns ac2
)
,cteMultiply AS
(--==== Create the display value for each product combination and a row# to derive Grp, Col, and Row from.
     -- The CROSS JOIN is also known as a "Cartesian Product" or "Square Join", like a times table.
 SELECT  RowNum = ROW_NUMBER() OVER (ORDER BY t1.N,t2.N)-1
        ,DisplayValue   = CONCAT(CONVERT(CHAR(3),t1.N),'x ',CONVERT(CHAR(3),t2.N),'= ',t1.N*t2.N)
   FROM      cteTally t1 --Multiplicand
  CROSS JOIN cteTally t2 --Multiplier
)--==== This is what is known as a "CROSSTAB".
 SELECT  Col1 = MAX(CASE 
                    WHEN Row = 10 THEN REPLICATE('-',13)
                    WHEN Col =  0 THEN DisplayValue
                    END)
        ,Col2 = MAX(CASE 
                    WHEN Row = 10 THEN REPLICATE('-',13)
                    WHEN Col =  1 THEN DisplayValue
                    END)
   FROM cteMultiply m
  CROSS APPLY (VALUES(RowNum/22, RowNum/11%2,RowNum))ca(Grp,Col,Row) --"DRY" it out.
  WHERE RowNum < 110
  GROUP BY ca.Grp, ca.Row
  ORDER BY ca.Grp, ca.Row
;

I got a bit carried away with doing the whole 10*10 thing. The code should be fairly easy to modify to suit. Here's the result set from that...

Col1           Col2
1  x 1  = 1    2  x 1  = 2
1  x 2  = 2    2  x 2  = 4
1  x 3  = 3    2  x 3  = 6
1  x 4  = 4    2  x 4  = 8
1  x 5  = 5    2  x 5  = 10
1  x 6  = 6    2  x 6  = 12
1  x 7  = 7    2  x 7  = 14
1  x 8  = 8    2  x 8  = 16
1  x 9  = 9    2  x 9  = 18
1  x 10 = 10   2  x 10 = 20
-------------  -------------
3  x 1  = 3    4  x 1  = 4
3  x 2  = 6    4  x 2  = 8
3  x 3  = 9    4  x 3  = 12
3  x 4  = 12   4  x 4  = 16
3  x 5  = 15   4  x 5  = 20
3  x 6  = 18   4  x 6  = 24
3  x 7  = 21   4  x 7  = 28
3  x 8  = 24   4  x 8  = 32
3  x 9  = 27   4  x 9  = 36
3  x 10 = 30   4  x 10 = 40
-------------  -------------
5  x 1  = 5    6  x 1  = 6
5  x 2  = 10   6  x 2  = 12
5  x 3  = 15   6  x 3  = 18
5  x 4  = 20   6  x 4  = 24
5  x 5  = 25   6  x 5  = 30
5  x 6  = 30   6  x 6  = 36
5  x 7  = 35   6  x 7  = 42
5  x 8  = 40   6  x 8  = 48
5  x 9  = 45   6  x 9  = 54
5  x 10 = 50   6  x 10 = 60
-------------  -------------
7  x 1  = 7    8  x 1  = 8
7  x 2  = 14   8  x 2  = 16
7  x 3  = 21   8  x 3  = 24
7  x 4  = 28   8  x 4  = 32
7  x 5  = 35   8  x 5  = 40
7  x 6  = 42   8  x 6  = 48
7  x 7  = 49   8  x 7  = 56
7  x 8  = 56   8  x 8  = 64
7  x 9  = 63   8  x 9  = 72
7  x 10 = 70   8  x 10 = 80
-------------  -------------
9  x 1  = 9    10 x 1  = 10
9  x 2  = 18   10 x 2  = 20
9  x 3  = 27   10 x 3  = 30
9  x 4  = 36   10 x 4  = 40
9  x 5  = 45   10 x 5  = 50
9  x 6  = 54   10 x 6  = 60
9  x 7  = 63   10 x 7  = 70
9  x 8  = 72   10 x 8  = 80
9  x 9  = 81   10 x 9  = 90
9  x 10 = 90   10 x 10 = 100
-------------  -------------

If you can live without the dashes, it gets even easier.

  • Related