2009-07-10 12 views
0

Je suis nouveau sur Microsoft SQL Server et j'ai été frustré par une requête GROUP BY qui ne fera pas ce que je veux. La table est la suivante:Groupe SQL Server par requête à l'aide de plusieurs valeurs

make model distancefrom distanceto driverid 
toyota yaris 358.2 368.2 401 
toyota yaris 368.2 378.7 103 
toyota yaris 378.7 382.2 103 
toyota yaris 382.2 392.2 103 
toyota yaris 392.2 403.6 103 
toyota yaris 403.6 414.3 103 
toyota yaris 414.3 419.4 103 
toyota yaris 419.4 430.2 103 
toyota yaris 430.2 439.2 401 
toyota yaris 439.2 446  401 
toyota yaris 446  457.2 401 
toyota yaris 457.2 460.1 401 
toyota yaris 460.1 468.6 401 
toyota yaris 468.6 480.3 401 
toyota yaris 480.3 486.2 103 
toyota yaris 486.2 490  103 
toyota yaris 490  501.1 103 
toyota yaris 501.1 512.5 103 
toyota yaris 512.5 523.1 103 
toyota yaris 523.1 532.6 401 
toyota yaris 532.6 542.7 401 
toyota yaris 542.7 551.1 401 

J'ai besoin de trouver la valeur de début et de fin pour chacun des driversid. Une requête GROUP BY normale utilisant un MIN et un MAX regroupe tous les pilotes qui sont identiques mais je dois les séparer. C'est à dire. la sortie devrait ressembler à ceci:

make model distancefrom distanceto driverid 
toyota yaris 358.2 368.2 401 
toyota yaris 368.2 430.2 103 
toyota yaris 430.2 480.3 401 
toyota yaris 480.3 523.1 103 
toyota yaris 523.1 551.1 512 

Toute aide serait appréciée.

+1

Pouvez-vous reformater cela s'il vous plaît? Essayez de sélectionner les données et en utilisant l'icône 0101 pour le marquer comme "code". –

+0

Vous voulez assembler des chaînes? En regardant DriverId = 401, vous avez deux lignes dans la sortie. 358.2 à 368.2 puis 430.2 à 480.3. Et la raison pour laquelle thee est deux lignes est en raison de l'écart entre 368.2 à 480.3 dans les données d'entrée. Est-ce exact? –

+0

Et quelle version de MS SQL Server? 2005 et 2008 ont des outils disponibles pour rendre cela plus facile que 2000 ne le fait pas. –

Répondre

1

Me semble que vous besoin de quelque chose comme ceci:

SELECT make, model, driverid, min(distancefrom), max(distancefrom), min(distanceto), max(distanceto) 
FROM table 
GROUP BY make, model, driverid 

Est-ce la requête que vous exécutez?

1
SELECT make, model, driverid 
FROM (
     SELECT make, model, driverid, 
       ROW_NUMBER() OVER (PARTITION BY make, model, driverid ORDER BY distancefrom) AS rns, 
       ROW_NUMBER() OVER (PARTITION BY make, model, driverid ORDER BY distancefrom DESC) AS rne 
     FROM mytable 
     ) q 
WHERE 1 IN (rns, rne) 

Si vous avez un index sur (make, model, driverid, distance), celui-ci peut être plus efficace:

SELECT m.make, m.model, m.driverid, 
     (
     SELECT TOP 1 distancefrom 
     FROM  mytable mi 
     WHERE mi.make = m.make 
       AND mi.model = m.model 
       AND mi.driverid = m.driverid 
     ORDER BY 
       distancefrom 
     ), 
     (
     SELECT TOP 1 distancefrom 
     FROM  mytable mi 
     WHERE mi.make = m.make 
       AND mi.model = m.model 
       AND mi.driverid = m.driverid 
     ORDER BY 
       distancefrom DESC 
     ) 
FROM (
     SELECT DISTINCT make, model, driverid 
     FROM mytable 
     ) m 
3

Vous voulez bien garder voyages séparés - les résultats que vous dites que vous voulez pour exemple le pilote 401 implique la première ligne, puis le min/max est exécuté sur le deuxième ensemble de lignes pour ce pilote. Il semble donc qu'il vous manque une colonne "JourneyID" ou similaire. La première rangée aurait une valeur pour JourneyID, le second ensemble de lignes aurait la même valeur de JourneyID mais serait différent de celui de la première rangée.

Si vous avez cette colonne, vous pouvez l'ajouter à la clause Group By.

0

Solution MS SQL 2005/2008. Ne fonctionne pas sur MS SQL 2000.

create table #journeySegment (make varchar(100) not null 
     , model varchar(100) not null 
     , distanceFrom decimal(10,2) not null 
     , distanceTo decimal(10, 2) not null 
     , driverId int not null -- References blah 
     , CONSTRAINT data_U unique (make, model, driverId, distanceFrom) 
     , CONSTRAINT data_FromTo_CHK check (distanceFrom <= distanceTo)) 


insert into #journeySegment values ('toyota', 'yaris', 358.2, 368.2, 401) 
insert into #journeySegment values ('toyota', 'yaris', 368.2, 378.7, 103) 
insert into #journeySegment values ('toyota', 'yaris', 378.7, 382.2, 103) 
insert into #journeySegment values ('toyota', 'yaris', 382.2, 392.2, 103) 
insert into #journeySegment values ('toyota', 'yaris', 392.2, 403.6, 103) 
insert into #journeySegment values ('toyota', 'yaris', 403.6, 414.3, 103) 
insert into #journeySegment values ('toyota', 'yaris', 414.3, 419.4, 103) 
insert into #journeySegment values ('toyota', 'yaris', 419.4, 430.2, 103) 
insert into #journeySegment values ('toyota', 'yaris', 430.2, 439.2, 401) 
insert into #journeySegment values ('toyota', 'yaris', 439.2, 446, 401) 
insert into #journeySegment values ('toyota', 'yaris', 446, 457.2, 401) 
insert into #journeySegment values ('toyota', 'yaris', 457.2, 460.1, 401) 
insert into #journeySegment values ('toyota', 'yaris', 460.1, 468.6, 401) 
insert into #journeySegment values ('toyota', 'yaris', 468.6, 480.3, 401) 
insert into #journeySegment values ('toyota', 'yaris', 480.3, 486.2, 103) 
insert into #journeySegment values ('toyota', 'yaris', 486.2, 490, 103) 
insert into #journeySegment values ('toyota', 'yaris', 490, 501.1, 103) 
insert into #journeySegment values ('toyota', 'yaris', 501.1, 512.5, 103) 
insert into #journeySegment values ('toyota', 'yaris', 512.5, 523.1, 103) 
insert into #journeySegment values ('toyota', 'yaris', 523.1, 532.6, 513) 
insert into #journeySegment values ('toyota', 'yaris', 532.6, 542.7, 513) 
insert into #journeySegment values ('toyota', 'yaris', 542.7, 551.1, 513) 

-- ASSUMPTIONS: 
-- journeySegments do not overlap. 
-- distanceFrom and distanceTo are exact numeric types. 

; with potentialJourney (make, model, journeyFrom, journeyTo, driverId, level) as 
    (-- Find the starting segment for each journey. 
    select make, 
     model, 
     distanceFrom, 
     distanceTo, 
     driverId, 
     0 
    from #journeySegment A 
    where not exists 
     (select * 
     from #journeySegment B 
     where B.make = A.Make 
     and B.model = A.model 
     and B.driverId = A.driverId 
     and B.DistanceTo = A.DistanceFrom) 
    union all 
    -- add on next segment. 
    select PJ.make 
     , PJ.model 
     , PJ.journeyFrom 
     , nextJS.distanceTo 
     , PJ.driverId 
     , PJ.level + 1 
    from potentialJourney PJ 
    inner join #journeySegment nextJS 
     on nextJS.make = PJ.Make 
     and nextJS.model = PJ.Model 
     and nextJs.driverId = PJ.driverId 
     and nextJs.distanceFrom = PJ.journeyTo) 
select M.make 
    , M.Model 
    , M.journeyFrom 
    , M.journeyTo 
    , M.driverId 
from potentialJourney M 
-- Eliminate the partial solutions 
where not exists 
    (select * 
    from potentialJourney S 
    where S.make = M.make 
    and S.model = M.model 
    and S.journeyFrom = M.journeyFrom 
    and S.driverId = M.driverId 
    and S.level > M.level) 
order by journeyFrom 
Questions connexes