10. december 2001 - 15:30Der er
17 kommentarer og 1 løsning
Crosstab query
Er det muligt at lave en såkaldt crosstab query på MS-SQL ?
Jeg har en tabel tblPrintLog med 3 felter fldDate, fldComputer og fldNumLabels og jeg vil gerne kunne se pr. dato hvor mange labels der er skrevet ud fra hver computer. I Access er det ikke noget problem, men jeg kan ikke lige gennemskue hvordan man laver sådan en i SQL.
Følgende udføres i Query Analyzer mod den ønskede database:
create function fn_tblPrintLogSummation -- Opretter en summering af data i tblPrintLog ud fra fldDate og fldComputer inden for datoafgrænsningerne ( @Param_FromDate datetime, @Param_ToDate datetime ) returns table as return ( -- top 100 percent er nødvendig for at kunne bruge order by. select top 100 percent fldDate, fldComputer, Sum(fldNumLabels) as NoOfLabels from tblPrintLog where (fldDate between @Param_FromDate and @Param_ToDate) group by fldDate, fldComputer order by fldDate, fldComputer )
Derefter udføres i Query Analyzer mod samme database:
create procedure sp_tblPrintLogCrossTab ( @Param_FromDate datetime, @Param_ToDate datetime ) as set nocount on
-- Vi skal bruge en midlertidig tabel. Denne bliver oprettet i tempdb, og kan kun ses fra host maskinen create table #tempTable ( fldDate datetime )
-- Indsæt alle de datoer, der er fundet i summeringen insert #tempTable (fldDate) select distinct fldDate from fn_tblPrintLogSummation(@Param_FromDate, @Param_ToDate) order by fldDate
-- Vi skal bruge en cursor for at finde alle de computernavne, der er fundet i summeringen declare @Comp sysname declare CompCursor cursor fast_forward for select distinct fldComputer from fn_tblPrintLogSummation(@Param_FromDate, @Param_ToDate) order by fldComputer
open CompCursor fetch next from CompCursor into @Comp
while @@fetch_status = 0 begin -- For hver computernavn, vi finder, opretter vi en kolonne med det navn. Derfor distinct i cursor-erklæringen. exec (\'alter table #tempTable add [\' + @Comp + \'] int not null default 0\')
-- Så skal den midlertidige tabel opdateres med antal labels for den dag for den computer. exec ( \'update #tempTable \' + \'set [\' + @Comp +\'] = logsum.NoOfLabels \' + \'from #tempTable T \' + \'inner join fn_tblPrintLogSummation(\'\'\' + @Param_FromDate + \'\'\', \'\'\' + @Param_ToDate +\'\'\') as logsum \' + \'on T.fldDate=logsum.fldDate \' + \'where logsum.fldComputer=\'\'\' + @Comp +\'\'\'\' )
-- Hent den næste fetch next from CompCursor into @Comp end
-- Så er vi færdige med cursoren close CompCursor deallocate CompCursor
-- Her tilføjes en total-kolonne per dato (kan udelades) alter table #tempTable add TotalNoOfLabels int not null default 0
-- Og opdatering af totalkolonnen exec ( \'update #tempTable \' + \'set [TotalNoOfLabels] = logsum.SumNoOfLabels \' + \'from #tempTable T \' + \'inner join ( select fldDate, Sum(NoOfLabels) as SumNoOfLabels \' + \'from fn_tblPrintLogSummation(\'\'\' + @Param_FromDate + \'\'\', \'\'\' + @Param_ToDate +\'\'\') \' + \'group by fldDate) as logsum \' + \'on T.fldDate=logsum.fldDate\')
-- Denne er væsentlig, hvis resultatet skal bruges fra VB. set nocount off
-- Dette returnerer krydstabuleringen select * from #tempTable
set nocount on
-- Så er vi færdige med den midlertidige tabel drop table #tempTable
Min query i Access ser ud som følgende TRANSFORM Sum([tblPrintLog].[fldNumLabels]) AS SumOffldNumLabels SELECT [tblPrintLog].[fldDate] AS Dato FROM tblPrintLog WHERE ((([tblPrintLog].[fldDate]) Is Not Null)) GROUP BY [tblPrintLog].[fldDate] PIVOT [tblPrintLog].[fldComputer];
Ja jeg bruger SQL 2000 ( Access som frontend i dette tilfælde - ellers Navision )
Jeg vil se om jeg kan få det til at spille med din løsning Benny.
Jeg har nu afprøvet din løsning Benny og bortset fra enkelte detaljer, så er det OK.
Den dato der returneres indeholder også klokkeslæt, men det må vel kunne ændres til at være smalldatetime! Næste opgave bliver så at få data over i Excel så jeg kan lave en fin graf over dem. Jeg må kunne flytte den midlertidige tabel over i min database og så bruge den som recordsource for mit Excel ark ( jeg ved godt at jeg kan lave crostabben i Excel, men jeg skal bruge de samme data til flere ting, så for at være sikker på at de er konsistente vil jeg helst lave så meget så tæt på de orginale data som muligt. )
Hvilket værktøj skal du bruge for at få det i Excel? Hvis du bruger VB eller Excel VBA, så kan du åbne den stored procedure som et forward only recordset (serverside) eller clientside (ADODB.Recordset)
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.