Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Rough Stats

Author  Topic 

Steve2106
Posting Yak Master

183 Posts

Posted - 2011-03-24 : 12:53:27
Hi There,

I need to show some statistics from a table. If we take the table layout to be:
RecId + Responsible + Carer + Type
1 | 1 | 3 | Play
2 | 5 | 3 | Play
3 | 5 | 2 | Play
4 | 3 | 1 | Study
5 | 2 | 3 | Play
6 | 3 | 1 | Study
7 | 1 | 2 | Exercise
8 | 4 | 2 | Exercise
9 | 1 | 3 | Play

I need to show, for a particular person say user 3, whose id is in either responsibe column or carer column, Total count of Records = 9
Responsible = 2 Carer = 4 And types
Play 3
Study 2
Exercise 0

Can that be done. Running through a table and calculating everything in 1 go?

Thanks for your help.

Best Regards,


Steve

robvolk
Most Valuable Yak

15732 Posts

Posted - 2011-03-24 : 13:38:40
It's not exactly the format you specified, but it does give you all the stats:
DECLARE @t TABLE(RecId INT NOT NULL PRIMARY KEY, Responsible INT NOT NULL, Carer INT NOT NULL, TYPE VARCHAR(20) NOT NULL)
INSERT @t SELECT
1,1,3,'Play' UNION ALL SELECT
2,5,3,'Play' UNION ALL SELECT
3,5,2,'Play' UNION ALL SELECT
4,3,1,'Study' UNION ALL SELECT
5,2,3,'Play' UNION ALL SELECT
6,3,1,'Study' UNION ALL SELECT
7,1,2,'Exercise' UNION ALL SELECT
8,4,2,'Exercise' UNION ALL SELECT
9,1,3,'Play'


;WITH CTE(Person, Side, TYPE) AS (
SELECT Person, Side, TYPE FROM (SELECT * FROM @t) a
UNPIVOT (Person FOR Side IN(Responsible, Carer)) b),
CTE2(Person, SideType) AS (
SELECT Person, Side FROM CTE
UNION ALL
SELECT Person, Type FROM CTE)
SELECT Person, Responsible, Carer, Play, Study, Exercise
FROM (select Person, SideType from CTE2) a
PIVOT(Count(SideType) FOR SideType IN(Responsible, Carer, Play, Study, Exercise)) b
The sections in red can be removed, and replace references to @t with your actual table name.
Go to Top of Page

Seventhnight
Master Smack Fu Yak Hacker

2878 Posts

Posted - 2011-03-24 : 13:43:27
how about:

Declare @t Table (
RecId int,
Responsible int,
Carer int,
Type varchar(10)
)
Insert Into @t Select 1, 1, 3, 'Play'
Insert Into @t Select 2, 5, 3, 'Play'
Insert Into @t Select 3, 5, 2, 'Play'
Insert Into @t Select 4, 3, 1, 'Study'
Insert Into @t Select 5, 2, 3, 'Play'
Insert Into @t Select 6, 3, 1, 'Study'
Insert Into @t Select 7, 1, 2, 'Exercise'
Insert Into @t Select 8, 4, 2, 'Exercise'
Insert Into @t Select 9, 1, 3, 'Play'



Select
A.Person,
Responsible = SUM(case when B.Responsible = A.Person then 1 else 0 end),
Carer = SUM(case when B.Carer = A.Person then 1 else 0 end),
Play = SUM(case when Type = 'Play' then 1 else 0 end),
Study = SUM(Case when Type = 'Study' then 1 else 0 end),
Exercise = SUM(case when Type = 'Exercise' then 1 else 0 end)
From
(
Select Person = Responsible From @t
Union
Select Person = Carer From @t
) A
Inner Join @t B
On A.Person = B.Responsible
Or A.Person = B.Carer
Group By A.Person


Corey

snSQL on previous signature "...Oh and by the way Seventhnight, your signature is so wrong! On so many levels, morally, gramatically and there is a typo!"
Go to Top of Page

Steve2106
Posting Yak Master

183 Posts

Posted - 2011-03-25 : 05:16:23
Hi There,
Thanks for the replies.
They both work great but I can understand the one from Corey better.

The stumbbleing block I have is that the example I gave is obviously fake and the type column holds an int that is related to the types table.
In reality I need to get a count for all the Types in the types table.
I could just create a:
Play = SUM(case when Type = 'Play' then 1 else 0 end),
For every type in the types table but then if someone adds a new type it will be broken. How can I loop through all the types and create a whatever = SUM(case when Type = 'whatever' then 1 else 0 end)

Thanks very much for taking time to help it really is appreciated.

Best Regards,



Steve
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2011-03-27 : 16:50:37
http://www.sqlteam.com/article/dynamic-cross-tabs-pivot-tables
Go to Top of Page

Steve2106
Posting Yak Master

183 Posts

Posted - 2011-03-28 : 06:58:06
quote:
Originally posted by robvolk

http://www.sqlteam.com/article/dynamic-cross-tabs-pivot-tables


Hi There,
Thanks for the reply.

I keep getting an error when I try to create the Stored Procedure.

Thanks for your help.

Best Regards,



Steve
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2011-03-28 : 07:07:10
If the error is "Syntax error near PIVOT", do a find-replace on "pivot" and change it to "_pivot".
Go to Top of Page

Steve2106
Posting Yak Master

183 Posts

Posted - 2011-03-28 : 08:46:39
quote:
Originally posted by robvolk

If the error is "Syntax error near PIVOT", do a find-replace on "pivot" and change it to "_pivot".


Hi There,

Sorry to bother you again.

There is @pivot ##pivot and pivot

Do I just change the one that is pivot to _pivot?

Thanks for your help,





Steve
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2011-03-28 : 10:35:13
Better to change all of them.
Go to Top of Page

Steve2106
Posting Yak Master

183 Posts

Posted - 2011-03-28 : 10:59:03
quote:
Originally posted by robvolk

Better to change all of them.


Hi RobVolk,

Really appreciate you trying to help but I still cannot get it to work.
Have you tried creating the stored procedure and then running one of the EXECUTE crosstab queries from the link you provided.
If you could try I would be greatful because then you will be able to see the trouble I am having.

Best Regards,



Steve
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2011-03-28 : 11:22:11
I made the code changes I specified and ran the following successfully:
exec crosstab 'SELECT A.Person FROM (select Responsible Person from #t union select Carer from #t) A
INNER JOIN #t B ON A.Person=B.Responsible OR A.Person=B.Carer
GROUP BY A.Person', 'Count(A.Person)', 'Type', '#t'
If you're getting an error, please post it. If you're not getting an error, then you'll have to elaborate on what's not working.
Go to Top of Page

Steve2106
Posting Yak Master

183 Posts

Posted - 2011-03-28 : 11:41:35
quote:
Originally posted by robvolk

I made the code changes I specified and ran the following successfully:
exec crosstab 'SELECT A.Person FROM (select Responsible Person from #t union select Carer from #t) A
INNER JOIN #t B ON A.Person=B.Responsible OR A.Person=B.Carer
GROUP BY A.Person', 'Count(A.Person)', 'Type', '#t'
If you're getting an error, please post it. If you're not getting an error, then you'll have to elaborate on what's not working.



Hi RobVolk,
Thanks for sticking with me.

This is my stored procedure:
ALTER PROCEDURE [dbo].[crosstab]
@select varchar(8000),
@sumfunc varchar(100),
@pivot varchar(100),
@table varchar(100)
AS

DECLARE @sql varchar(8000), @delim varchar(1)
SET NOCOUNT ON
SET ANSI_WARNINGS OFF

EXEC ('SELECT ' + @pivot + ' AS _pivot INTO _pivot FROM ' + @table + ' WHERE 1=2')
EXEC ('INSERT INTO _pivot SELECT DISTINCT ' + @pivot + ' FROM ' + @table + ' WHERE '
+ @pivot + ' Is Not Null')

SELECT @sql='', @sumfunc=stuff(@sumfunc, len(@sumfunc), 1, ' END)' )

SELECT @delim=CASE Sign( CharIndex('char', data_type)+CharIndex('date', data_type) )
WHEN 0 THEN '' ELSE '''' END
FROM tempdb.information_schema.columns
WHERE table_name='_pivot' AND column_name='_pivot'

SELECT @sql=@sql + '''' + convert(varchar(100), _pivot) + ''' = ' +
stuff(@sumfunc,charindex( '(', @sumfunc )+1, 0, ' CASE ' + @pivot + ' WHEN '
+ @delim + convert(varchar(100), _pivot) + @delim + ' THEN ' ) + ', ' FROM _pivot

DROP TABLE _pivot

SELECT @sql=left(@sql, len(@sql)-1)
SELECT @select=stuff(@select, charindex(' FROM ', @select)+1, 0, ', ' + @sql + ' ')

EXEC (@select)
SET ANSI_WARNINGS ON

This is what I have executed:
exec crosstab 'SELECT A.Person FROM (select Responsible Person from #t union select Carer from #t) A
INNER JOIN #t B ON A.Person=B.Responsible OR A.Person=B.Carer
GROUP BY A.Person', 'Count(A.Person)', 'Type', '#t'

These are the errors:
Msg 208, Level 16, State 0, Line 1
Invalid object name '#t'.
Msg 208, Level 16, State 0, Line 1
Invalid object name '#t'.
Msg 208, Level 16, State 1, Procedure crosstab, Line 24
Invalid object name '_pivot'.

Thanks again for your help.
If you could post the stored procedure you ran against I would appreciate it.

Best Regards,



Steve
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2011-03-28 : 11:51:09
Use this version:
ALTER PROCEDURE crosstab 
@select varchar(8000),
@sumfunc varchar(100),
@_pivot varchar(100),
@table varchar(100)
AS

DECLARE @sql varchar(8000), @delim varchar(1)
SET NOCOUNT ON
SET ANSI_WARNINGS OFF

EXEC ('SELECT ' + @_pivot + ' AS _pivot INTO ##_pivot FROM ' + @table + ' WHERE 1=2')
EXEC ('INSERT INTO ##_pivot SELECT DISTINCT ' + @_pivot + ' FROM ' + @table + ' WHERE '
+ @_pivot + ' Is Not Null')

SELECT @sql='', @sumfunc=stuff(@sumfunc, len(@sumfunc), 1, ' END)' )

SELECT @delim=CASE Sign( CharIndex('char', data_type)+CharIndex('date', data_type) )
WHEN 0 THEN '' ELSE '''' END
FROM tempdb.information_schema.columns
WHERE table_name='##_pivot' AND column_name='_pivot'

SELECT @sql=@sql + '''' + convert(varchar(100), _pivot) + ''' = ' +
stuff(@sumfunc,charindex( '(', @sumfunc )+1, 0, ' CASE ' + @_pivot + ' WHEN '
+ @delim + convert(varchar(100), _pivot) + @delim + ' THEN ' ) + ', ' FROM ##_pivot

DROP TABLE ##_pivot

SELECT @sql=left(@sql, len(@sql)-1)
SELECT @select=stuff(@select, charindex(' FROM ', @select)+1, 0, ', ' + @sql + ' ')

EXEC (@select)
SET ANSI_WARNINGS ON
Go to Top of Page

Steve2106
Posting Yak Master

183 Posts

Posted - 2011-03-28 : 12:07:50
Hi RobVolk,

That's great getting closer. That works with the Pubs Database but I cannot get it to work on my database with your latest execute code:
exec crosstab 'SELECT A.Person FROM (select Responsible Person from #t union select Carer from #t) A
INNER JOIN #t B ON A.Person=B.Responsible OR A.Person=B.Carer
GROUP BY A.Person', 'Count(A.Person)', 'Type', '#t'

I get errors:
Msg 208, Level 16, State 0, Line 1
Invalid object name '#t'.
Msg 208, Level 16, State 0, Line 1
Invalid object name '#t'.
Msg 208, Level 16, State 1, Procedure crosstab, Line 26
Invalid object name '##_pivot'.

I appreciate you giving the stored procedure code. If I could just get there with this last bit would be fantastic.

All the best,




Steve
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2011-03-28 : 12:12:20
Sorry, I forgot to mention I used Seventhnight's code and changed it to a temp table from a table variable. Run this once before the crosstab:
create Table #t(
RecId int,
Responsible int,
Carer int,
Type varchar(10)
)
Insert Into #t Select 1, 1, 3, 'Play'
Insert Into #t Select 2, 5, 3, 'Play'
Insert Into #t Select 3, 5, 2, 'Play'
Insert Into #t Select 4, 3, 1, 'Study'
Insert Into #t Select 5, 2, 3, 'Play'
Insert Into #t Select 6, 3, 1, 'Study'
Insert Into #t Select 7, 1, 2, 'Exercise'
Insert Into #t Select 8, 4, 2, 'Exercise'
Insert Into #t Select 9, 1, 3, 'Play'
Just change references for "#t" to your regular table name:
exec crosstab 'SELECT A.Person FROM (select Responsible Person from myTable union select Carer from myTable) A
INNER JOIN myTable B ON A.Person=B.Responsible OR A.Person=B.Carer
GROUP BY A.Person', 'Count(A.Person)', 'Type', 'myTable'
Go to Top of Page

Steve2106
Posting Yak Master

183 Posts

Posted - 2011-03-28 : 12:29:39
Hi RobVolk,

That's amazing and it works. Thankyou very much for taking the time to teach me this it really is appreciated.

My only problem now is that the Type description is in a different table and I need to show these description as the column headers are 1,3,5,6,8 etc not really informative to the user.

All the best,

Steve.
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2011-03-28 : 13:02:36
Try something like this:
exec crosstab 'SELECT A.Person FROM (select Responsible Person from myTable union select Carer from myTable) A
INNER JOIN myTable B ON A.Person=B.Responsible OR A.Person=B.Carer
INNER JOIN Types T ON B.Type=T.Type
GROUP BY A.Person', 'Count(A.Person)', 'T.TypeDescription', 'myTable'
Change table/column names as needed.
Go to Top of Page

Steve2106
Posting Yak Master

183 Posts

Posted - 2011-03-28 : 13:30:24
Hi RobVolk,

I am at home now so I'll have to try that tomorrow. I did get it sort of working by using a view but your way looks much better.

Thanks for a great day, I mark it down as successfull thanks to all your help. I learnt a lot.

Best Regards,


Steve.
Go to Top of Page
   

- Advertisement -