Click here to monitor SSC

Lionel Clarke

Software Engineer - Red Gate Software

Sql Puzzle 5

Published Friday, December 30, 2005 5:27 PM

/*
I hope that everybody had a good Christmas. I apologize for the lack of new puzzles but I have been using up the remains of my Holiday. Since it is the New Year I thought we should start it off with a nice easy but fun puzzle.

Recently I have been struggling writing some internal Red Gate reports and while trying to get Reporting Services to draw bar graphs I thought wouldn’t it be much easier if we could just use SQL Server to generate all these reports internally. So this week’s puzzle is simple. Given some sales results generate an ASCII art bar chart representing the results. Whereas previous puzzles had either a right or a wrong answer with this one I would like to encourage a bit of competition so let’s see who can product the best looking ASCII art chart.

Since space is limited I am only going to give people 4 columns to put on the chart. One column for each quarter of the year. The sales data is in a table cunningly labeled @SalesResults. This table has a column for which quarter of the year the results belong to which is a number from 1 to 4. There is also an AmountSold column for the amount of things sold in that quarter. I am also giving you a helper table called Sequence which just contains the numbers 0 to 100. A sequence table is the Swiss Army Knife of all database tables and is a very useful thing in any database. As usual with these puzzles you should be done with one top level select statement though you can use as many derived tables subselects and unions as you like. Defiantly no DDL, variables or Transact SQL Control statements like IF and WHILE. My solution is as follows:

20 |                                        
   |                                        
   |                                        
   |                                        
   |                                        
   |                         ----           
   |                        |    |          
   |                        |    |          
   |     ----               |    |     ----
   |    |    |              |    |    |    |
10 |    |    |              |    |    |    |
   |    |    |     ----     |    |    |    |
   |    |    |    |    |    |    |    |    |
   |    |    |    |    |    |    |    |    |
   |    |    |    |    |    |    |    |    |
   |    |    |    |    |    |    |    |    |
   |    |    |    |    |    |    |    |    |
   |    |    |    |    |    |    |    |    |
   |    |    |    |    |    |    |    |    |
   |    |    |    |    |    |    |    |    |
0  |    |    |    |    |    |    |    |    |
   ---------------------------------------------
          Q1        Q2        Q3        Q4  

Have fun.

Lionel

*/

SET NOCOUNT ON

DECLARE @Sequence TABLE
(
    i INT NOT NULL
)

DECLARE @i INT
SET @i=0
WHILE(@i < 100)
BEGIN
    INSERT INTO @Sequence(i) VALUES (@i)
    SET @i = @i + 1
END

DECLARE @SalesResults TABLE
(
    [Quarter] INT PRIMARY KEY CHECK([Quarter] BETWEEN 1 AND 4),
    [AmountSold] INT NOT NULL
)

INSERT INTO @SalesResults([Quarter], [AmountSold])
    SELECT 1, 12
INSERT INTO @SalesResults([Quarter], [AmountSold])
    SELECT 2, 9
INSERT INTO @SalesResults([Quarter], [AmountSold])
    SELECT 3, 15
INSERT INTO @SalesResults([Quarter], [AmountSold])
    SELECT 4, 12

SET NOCOUNT OFF
by Lionel

Comments

 

Phil Factor said:

/*<pre>
Well, here is one way of attacking the problem. For some reason, i'm currently addicted to cross joins so I used one here, and did a pivot-table flip on the results
Then a good messy hack with case statements to produce the ASCII art.

I didn't like the horizontal axis Lionel did which should have been on Zero
So I changed that.

I used the old ASCII Art convention of using + signs for orthoganal intersections. Looks a bit nicer. I also felt that the gaps between the bar should have been narrower

OK So far it is pretty damned easy but what if profits shot up and so one had to scale the vertical access? Also, what if one was to do it by month or an arbitrary no. of values?*/

select
case when ii in (0,10,20) then ' '+convert(char(2),ii) else ' ' end
+case ii when 0 then '+--' when -1 then ' ' else '| ' end+
+case when ii in (Quarter1,0) then '+---+' when ii=-1 then ' 1 ' when ii<Quarter1 then'| |' else ' 'end
+case ii when 0 then '--' else ' ' end+
+case when ii in (Quarter2,0) then '+---+' when ii=-1 then ' 2 ' when ii<Quarter2 then'| |' else ' 'end
+case ii when 0 then '--' else ' ' end+
+case when ii in (Quarter3,0) then '+---+' when ii=-1 then ' 3 ' when ii<Quarter3 then'| |' else ' 'end
+case ii when 0 then '--' else ' ' end+
+case when ii in (Quarter4,0) then '+---+'when ii=-1 then ' 4 ' when ii<Quarter4 then'| |' else ' 'end
+case ii when 0 then '--' else '' end
from
(
Select
[ii]=i-1,
[Quarter1]=sum(case when quarter=1 then amountSold Else 0 end) ,
[Quarter2]=sum(case when quarter=2 then amountSold Else 0 end),
[Quarter3]=sum(case when quarter=3 then amountSold Else 0 end),
[Quarter4]=sum(case when quarter=4 then amountSold Else 0 end)
from @sequence cross join @salesresults
where i <= 21
group by i
)f
order by ii desc

/* I don't know how to display a comment in a non-proportional font so I can't display
the results. I've put a query to Teligent Systems (who wrote Community Server) and if I hear back I'll let everyone know how to do it.

Actually, just displaying spaces and tabs would be nice </pre>*/
January 1, 2006 6:39 PM
 

Dave F said:

This is Phil's code.  Didn't work for me at first pass, but the below does.

select
case when ii in (0,10,20) then ' '+convert(char(2),ii) else '   ' end
+case ii when 0 then '+--' when -1 then '  ' else '|  ' end+
+case when ii in (Quarter1,0) then '+---+' when ii=-1 then '   1 ' when ii<Quarter1 then'|   |' else '     'end
+case ii when 0 then '--' else '  ' end+
+case when ii in (Quarter2,0) then '+---+' when ii=-1 then '   2 ' when ii<Quarter2 then'|   |' else '     'end
+case ii when 0 then '--' else '  ' end+
+case when ii in (Quarter3,0) then '+---+' when ii=-1 then '   3 ' when ii<Quarter3 then'|   |' else '    'end
+case ii when 0 then '--' else '  ' end+
+case when ii in (Quarter4,0) then '+---+'when ii=-1 then '   4 ' when ii<Quarter4 then'|   |' else '    'end
+case ii when 0 then '--' else '' end
from
(
Select
[ii]=i-1,
[Quarter1]=sum(case when quarter=1 then amountSold Else 0 end) ,
[Quarter2]=sum(case when quarter=2 then amountSold Else 0 end),
[Quarter3]=sum(case when quarter=3 then amountSold Else 0 end),
[Quarter4]=sum(case when quarter=4 then amountSold Else 0 end)
from @sequence cross join @salesresults
where i <= 21
group by i
)f
order by ii desc
November 7, 2007 11:06 AM
 

Fun with SQL (games, painting, puzzles) « 1st blog, pre-beta version… said:

January 24, 2010 2:04 AM
You need to sign in to comment on this blog
<December 2005>
SuMoTuWeThFrSa
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567
How to Kill a Company in One Step or Save it in Three
 The majority of companies that suffer a major data loss subsequently go out of business. David Wesley... Read more...

Migrating from OCS 2007 R2 to Lync: Part 4
 Having migrated the rest of our users and legacy resources across and started getting ready to... Read more...

Automated Script-generation with Powershell and SMO
 In the first of a series of articles on automating the process of building, modifying and copying SQL... Read more...

Seth Godin: Big in the IT Business
 Seth Godin has transformed our understanding of marketing in IT. He invented the concept of 'permission... Read more...

Using SQL Test Database Unit Testing with TeamCity Continuous Integration
 With database applications, the process of test and integration can be frustratingly slow because so... Read more...