Reputation: 39986
I have a "datadump" table that has a bunch of mixed performance-related data. Something like:
MachID TestDate MachType Value1 Value2 ...
00001 01/01/09 Server 15 48
00001 01/02/09 Server 16 99
19999 01/01/09 Switch 32 4.9880
19999 01/02/09 Switch 32 5.8109
The trick is that the "values" columns MEAN different things for different types of machines. So we have a "xRef" table that looks like:
MachType Column Description
Server Value1 Users Connected
Server Value2 % CPU _total
Switch Value1 Number of Ports
Switch Value2 packets/ms
...
I know, weird structure, but I didn't make it, and can't change it.
I'd like to somehow "inner join" these so I can query the appropriate column headers based on the type of data. Something like this for the servers:
MachID TestDate MachType Users Connected % CPU _total Total RAM
00001 01/01/09 Server 15 48 4096
00001 01/02/09 Server 16 99 4096
and this for the switches:
MachID TestDate MachType Number of Ports packets/ms Total Cumulative kb
19999 01/01/09 Switch 32 4.9880 1024547
19999 01/02/09 Switch 32 5.8109 1029450
Is there a way to do this without doing individual hard-coded queries for each type?
Note: I will only need to query one type of object at a time. Most likely, I'll only be looking at all results between particular dates for a single MachID, if that helps. This is MS SQL 2000.
Thanks!
Upvotes: 0
Views: 897
Reputation: 4533
A dynamic sql option would be (written out as a query rather than made into a proc):
declare @machtype varchar(40) --stored proc parameter?
set @machtype = 'Switch' --or 'Server'
declare @sql nvarchar(4000)
set @sql = 'select
MachID,
TestDate,
MachType,
Value1 as ''' + (select [Description] from dbo.xref where machtype = @machtype and [Column] = 'Value1') + ''',
Value2 as ''' + (select [Description] from dbo.xref where machtype = @machtype and [Column] = 'Value2') + ''',
Value3 as ''' + (select [Description] from dbo.xref where machtype = @machtype and [Column] = 'Value3') + '''
from
dbo.datadump
where
machtype = ''' + @machtype + ''''
exec sp_executesql @sql
If you find that simply too ugly for you then wrapping the logic for getting the column name in a function would tidy it up:
create function dbo.ColNameForDataDump(
@machtype varchar(40),
@column varchar(40)
)
RETURNS varchar(40)
as
begin
declare @col_desc varchar(40)
select
@col_desc = [description]
from
dbo.xref
where
machtype = @machtype
and [column] = @column
return @col_desc
end
Then your dynamic SQL will look more like:
declare @machtype varchar(40) --stored proc parameter?
set @machtype = 'Switch' --or 'Server'
declare @sql nvarchar(4000)
set @sql = 'select
MachID,
TestDate,
MachType,
Value1 as ''' + dbo.ColNameForDataDump(@machtype, 'Value1') + ''',
Value2 as ''' + dbo.ColNameForDataDump(@machtype, 'Value2') + ''',
Value3 as ''' + dbo.ColNameForDataDump(@machtype, 'Value3') + '''
from
dbo.datadump
where
machtype = ''' + @machtype + ''''
exec sp_executesql @sql
Finally a passing point / comment on the code above: you mentioned that you are on SQL Server 2000 so make sure when you do have to write some dynamic sql to define it as an nvarchar and use sp_executesql to call it...thereby negating some of the performance pain of having to go dynamic.
Upvotes: 1
Reputation: 89711
This will do them all together - you can modify as appropriate if you want them all split up.
DECLARE @template AS varchar(max)
DECLARE @sql AS varchar(max)
DECLARE @column_list AS varchar(max)
SELECT @column_list = COALESCE(@column_list + ', ', '')
+ QUOTENAME([Description])
FROM xRef
SET @template = ';
WITH up
AS (
SELECT MachID
,TestDate
,MachType
,[COLUMN]
,[Value]
FROM datadump UNPIVOT ( [Value] FOR [Column] IN ([Value1], [Value2]) ) AS unpvt
)
,ready AS (
SELECT machID
,TestDate
,up.MachType
,[Description]
,up.[Value]
FROM up
INNER JOIN xRef
ON xRef.machType = up.MachType
AND xRef.[Column] = up.[Column]
)
SELECT * FROM ready
PIVOT (SUM([Value]) FOR [Description] IN ({@column_list})) AS pvt
'
machID TestDate MachType Users Connected % CPU _total Number of Ports packets/ms
------ ----------------------- -------- --------------------------------------- --------------------------------------- --------------------------------------- ---------------------------------------
00001 2009-01-01 00:00:00.000 Server 15.000000000000000 48.000000000000000 NULL NULL
00001 2009-01-02 00:00:00.000 Server 16.000000000000000 99.000000000000000 NULL NULL
19999 2009-01-01 00:00:00.000 Switch NULL NULL 32.000000000000000 4.988000000000000
19999 2009-01-02 00:00:00.000 Switch NULL NULL 32.000000000000000 5.810900000000000
Upvotes: 1
Reputation: 47392
Since you can't change the data model I would suggest putting the presentation code into the presentation layer of your application. Have a table that gives you the column headings to use based on the results being requested and go from there.
Upvotes: 0
Reputation: 4426
Create a table storing the header-name for each value for that individual type of query.
Then, create a stored procedure and use Dynamic SQL to fill in the column name as drawn from that table.
Upvotes: 0