November 18, 2003 at 2:03 am
Hi,
I have a proc that produces an output with a varying amount of columns (depending on the parameters passed).
What I would like to do is create a table (doesn't matter if it's a temp) based on the output of this procedure. I cannot create the table before I run the proc because the quantity of columns could be different each time the proc is run.
Does anybody know if this is possible.
November 18, 2003 at 2:43 am
Create the 'stub' of a temp table (say, just an identity column) with a standard name before calling the stored proc. Inside the stored proc you could add the columns you need and populate the table. Presumably you build the query string in the sp, so you could build the 'alter table' string at the same time. Because the table was not created inside the stroed proc, it will not be dropped when the sp completes, and will still be visible to the calling process.
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
November 18, 2003 at 5:09 am
stax68 - thank you, could you show me what you mean please?
November 18, 2003 at 5:27 am
Use the SELECT...INTO...FROM... syntax, e.g.:
SELECT <select list from your query here>
INTO ##TempTable
FROM <rest of your query here>
--Jonathan
--Jonathan
November 18, 2003 at 6:54 am
OK still can't get it to work. Here is a simular example of what I'm doing using the Northwind database.
This is the proc I'm executing
exec crosstab2 'select top 20 shipvia from orders group by shipvia','count(shipvia)','year(orderdate)','orders','shipvia'
Here is the output
shipvia199619971998199619971998199619971998
3581227558122755812275
2561531175615311756153117
1381337838133783813378
Now the years will obviously inccrease so I 'don't want to keep tweaking the proc.
November 18, 2003 at 7:24 am
quote:
OK still can't get it to work. Here is a simular example of what I'm doing using the Northwind database.This is the proc I'm executing
exec crosstab2 'select top 20 shipvia from orders group by shipvia','count(shipvia)','year(orderdate)','orders','shipvia'
Here is the output
shipvia199619971998199619971998199619971998
3581227558122755812275
2561531175615311756153117
1381337838133783813378
Now the years will obviously inccrease so I 'don't want to keep tweaking the proc.
Rewrite your stored procedure to select into the (global temporary?) table instead of just returning the result set.
--Jonathan
--Jonathan
November 18, 2003 at 11:30 am
Try...
-- Not recommended to use in a loop, does take a little longer to execute
-- Generic example ...
select * from OpenRowset('SQLOLEDB',
'Server=(local);Trusted_Connection=yes',
'Exec Master.dbo.sp_help ')
-- Example with your call (you need to replace [DataBaseName])
select * from OpenRowset('SQLOLEDB',
'Server=(local);Trusted_Connection=yes',
'Exec [DataBaseName].dbo.crosstab2
''select top 20 shipvia from orders group by shipvia'',
''count(shipvia)'', ''year(orderdate)'', ''orders'', ''shipvia'' ')
Once you understand the BITs, all the pieces come together
November 19, 2003 at 6:36 am
Not a good solution but if the process time is small you could change the proc to have additional parameters, one to return the number of years and another to request the resultset or not. Then you could call the proc requesting the number of years, create the temp table, then call again to get resultset into the temp table.
Ah! Just seen the flaw , you want the years. OK, one parameter to request list of years or the data.
Edited by - davidburrows on 11/19/2003 06:38:09 AM
Far away is close at hand in the images of elsewhere.
Anon.
November 19, 2003 at 3:36 pm
-- You have two options that I can think of:
-- 1) Users use the pivottable functionality built into olap services (i.e. in excel its a snap) and just provide them a sp to call that returns non-pivot result set.
-- 2) Use string executes
--
-- My opinion: SQL has a limit on the number of fields you can have. There is also a limit on the number
-- of columns a user can actually interpret into something useful- typically the simpler a report the better.
-- For example, if they want to see beyond a year of data, they likely want it aggregated down by quarter
-- or by year. This realistically limits the number of columns you will really need to output.
--
-- Beyond that, it is likely custom work will have to be done anyhow. I typically just use columns named
-- by their sequence and tell them what the starting period is, or have the procedure pass back the starting period.
-- If the need for extensive analysis data is great, its good to set them up with excel with its pivot table utility
-- and a read-only copy of the data (like movelog or something). Outside of that, it is an OLAP project, which
-- is an animal all its own.
--
-- If SQL itself just HAS to give it specific column names instead of just a sequence number, you can do something like I
-- did below. Run it in the northwind db.
--
-- This example uses temp tables. I would think you could set one up that only used the sum(case when..) for the fields
-- and build a string to execute that may have less of a footprint.
set nocount on
drop table #x
go
drop table #y
go
declare @SQLStr varchar(8000)
select
count(*) as OrderCount
,ShipVia
,year(OrderDate) as OrderDateYear
into #x
from
Orders
group by
ShipVia
,year(OrderDate)
order by
ShipVia
,year(OrderDate)
create table #y (ShipVia int not null)
-- while this can be done inside the data pivot loop by checking MVs, this is clearer since it's only an example.
declare cFieldsToAdd insensitive cursor
for
select distinct 'alter table #y add ODY'+ltrim(str(OrderDateYear))+' int null' from #x
for read only
open cFieldsToAdd
fetch next from cFieldsToAdd into @SQLStr
while @@fetch_status = 0
begin
execute(@SQLStr)
fetch next from cFieldsToAdd into @SQLStr
end
close cFieldsToAdd
deallocate cFieldsToAdd
declare
@cOrderDateYear int
,@cOrderCount int
,@cShipVia int
,@LastShipVia int
set @LastShipVia = -1
-- fill the pivot table
declare cDataToPivot insensitive cursor
for
select * from #x order by ShipVia, OrderDateYear
for read only
open cDataToPivot
fetch next from cDataToPivot into @cOrderCount, @cShipVia, @cOrderDateYear
while @@Fetch_Status = 0
begin
if @LastShipVia <> @cShipVia
set @SQLStr = 'insert into #y (ShipVia, ODY'+ltrim(str(@cOrderDateYear))+') values ('+ltrim(str(@cShipVia))+', '+ltrim(str(@cOrderCount))+')'
else
set @SQLStr = 'update #y set ODY'+ltrim(str(@cOrderDateYear))+' = '+ltrim(str(@cOrderCount))+' where ShipVia = '+ltrim(str(@cShipVia))
execute(@SQLStr)
set @LastShipVia = @cShipVia
fetch next from cDataToPivot into @cOrderCount, @cShipVia, @cOrderDateYear
end
close cDataToPivot
deallocate cDataToPivot
select * from #y order by ShipVia
November 19, 2003 at 3:38 pm
Sorry for the formatting. I hate it when forum interfaces remove all my formatting tabs. Unfortunately I am too used to tab instead of space formatting to change in isql.
Is there a way to make it keep my tab formatting?
November 20, 2003 at 1:30 am
quote:
Hi,I have a proc that produces an output with a varying amount of columns (depending on the parameters passed).
What I would like to do is create a table (doesn't matter if it's a temp) based on the output of this procedure. I cannot create the table before I run the proc because the quantity of columns could be different each time the proc is run.
Does anybody know if this is possible.
You may like to use System Stored Procedure Called sp_executesql and pass your parameters the complete help you can get from Help online Good Luck
January 7, 2004 at 4:10 pm
I may be a bit off beam on this one however, having read so many requests for a CROSSTAB (TRANSFORM/PIVOT) function in SQL Server, I wondered if a procedure I wrote (sp_XTAB) might be of benefit to some.
It produces crosstab views with a (current) capacity of up to (around) 100 columns depending upon the size of the query generated from x7 parameters.
EXEC sp_XTAB 'db_name', 'name_for_output_view', 'source_table' ,'output_field' ,'pivot_field' ,'calc_field' ,'calc'
No need for special tables or anything else. I guess the same PRINCIPAL could be used to generate tables, if required. sp_STAB???
Wish I'd seen your code sample before I wrote mine as there are some similarities. I think the main difference is that you have scoped by one level while I used two.
This is my first sight of Server Central and I am most impressed.
Regards,
Ian
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply