5

Just for fun, I wanted to create a visual dice roller using SQL (I know that this is hardly what the language is designed for).

I've come up with the code below, which will roll as many dice as you like (@Dice) and show a visual representation of each, like that of a normal six-sided die.

CREATE TABLE #Row1 ([1] CHAR(1), [2] CHAR(1), [3] CHAR(1))
CREATE TABLE #Row2 ([1] CHAR(1), [2] CHAR(1), [3] CHAR(1))
CREATE TABLE #Row3 ([1] CHAR(1), [2] CHAR(1), [3] CHAR(1))

DECLARE @Number INT
DECLARE @Count INT = 1
DECLARE @Dice INT = 2

WHILE @Count <= @Dice
BEGIN
SET @Number = ROUND(RAND(CONVERT(VARBINARY,NEWID()))*6,0,1)+1

INSERT INTO #Row1 ([1], [2], [3]) VALUES (
 CASE WHEN @Number < 4 THEN ''
                       ELSE '•'
                       END
,''
,CASE WHEN @Number = 1 THEN ''
                       ELSE '•'
                       END
)

INSERT INTO #Row2 ([1], [2], [3]) VALUES (
 CASE WHEN @Number <> 6 THEN ''
                        ELSE '•'
                        END
,CASE WHEN @Number % 2 = 0 THEN ''
                           ELSE '•'
                           END
,CASE WHEN @Number <> 6 THEN ''
                        ELSE '•'
                        END
)

INSERT INTO #Row3 ([1], [2], [3]) VALUES (
 CASE WHEN @Number = 1 THEN ''
                       ELSE '•'
                       END
,''
,CASE WHEN @Number < 4 THEN ''
                       ELSE '•'
                       END
)

SELECT * FROM #Row1
UNION ALL
SELECT * FROM #Row2
UNION ALL
SELECT * FROM #Row3

TRUNCATE TABLE #Row1
TRUNCATE TABLE #Row2
TRUNCATE TABLE #Row3

SET @Count += 1
END

DROP TABLE #Row1
DROP TABLE #Row2
DROP TABLE #Row3

My question is, how could this be made more efficient? Is there a way to do this without so many UNIONs?

I'd also be interested in seeing any ideas people may have for expanding on this/making it more interesting!

Simmo33
  • 73
  • 1
  • 7
  • 1
    Sorry, but in this category I don't think you can get any more interesting than [drawing Mandelbrot sets in T-SQL](https://stackoverflow.com/q/314864/4137916). That's not to say you shouldn't try... – Jeroen Mostert Apr 12 '19 at 13:13

1 Answers1

4

Use a table variable instead of temporary tables. And include all three rows in the same table variable:

DECLARE @Rows TABLE ([Row] INT, [1] NCHAR(1), [2] NCHAR(1), [3] NCHAR(1));
DECLARE @Number INT;
DECLARE @Count INT = 1;
DECLARE @Dice INT = 2;

WHILE @Count <= @Dice
BEGIN
SET @Number = ROUND(RAND(CONVERT(VARBINARY,NEWID()))*6,0,1)+1;

INSERT INTO @Rows ([Row], [1], [2], [3]) VALUES
(
     1
    ,CASE WHEN @Number < 4 THEN N'' ELSE N'•' END
    ,N''
    ,CASE WHEN @Number = 1 THEN N'' ELSE N'•' END
),
(
     2
    ,CASE WHEN @Number <> 6 THEN N'' ELSE N'•' END
    ,CASE WHEN @Number % 2 = 0 THEN N'' ELSE N'•' END
    ,CASE WHEN @Number <> 6 THEN N'' ELSE N'•' END
),
(
     3
    ,CASE WHEN @Number = 1 THEN N'' ELSE N'•' END
    ,N''
    ,CASE WHEN @Number < 4 THEN N'' ELSE N'•' END
);

SELECT [1], [2], [3] FROM @Rows ORDER BY [Row];
DELETE FROM @Rows;

SET @Count += 1;
END;

Edit:

I updated my solution, so that the three records are inserted in a single INSERT statement, instead of three separate INSERT statements for each record.

Bart Hofland
  • 3,700
  • 1
  • 13
  • 22
  • 2
    You JUST beat me to it. It might be worth removing the `order by` because that happens by default and then you can eliminate the `Row` column to match the OP's results: `SELECT [1], [2], [3] FROM @Rows;` – mtr.web Apr 12 '19 at 13:13
  • Ah, nice, I didn't even know table variables were a thing.... Definitely something I will look into more! – Simmo33 Apr 12 '19 at 13:17
  • 1
    @mtr.web :) Thanks for the tip about the ordering. I think you might be very right about that. But personally, I have some bad experiences with default ordering by SQL Server. So if I need a functionally necessary ordering, I always set it explicitly. Just to be certain. ;) – Bart Hofland Apr 12 '19 at 13:18
  • 1
    I've had similar experiences, so I agree. In this case, it is being set by the order that you are entering them. So, as far as I know, it should always be in the right order (for this use case) – mtr.web Apr 12 '19 at 13:36
  • 1
    A very, very minor note, but I'd recommend using `NCHAR`. That `•` is representable in the database collation is not a given. – Jeroen Mostert Apr 12 '19 at 13:39