2009-07-10 1 views
0

Я новичок в Microsoft SQL Server и разочарован запросом GROUP BY, который не будет делать то, что я хочу. Таблица такова:Группа SQL Server по запросу с использованием нескольких значений

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 

Мне нужно найти начальное и конечное значение для каждого из драйверов. Обычный запрос GROUP BY с использованием MIN и MAX объединяет все драйверы , которые являются одними и теми же вместе, но мне нужно сохранить каждый отдельный. То есть вывод должен выглядеть следующим образом:

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 

Любая помощь будет оценена.

+1

Можете ли вы переформатировать это, пожалуйста? Попробуйте выбрать данные и использовать значок 0101, чтобы отметить его как «код». –

+0

Вы хотите собрать цепочки? Глядя на DriverId = 401, на выходе есть две строки. От 358,2 до 368,2, а затем от 430,2 до 480,3. И причина в том, что у вас две строки, из-за разрыва между 368,2 и 480,3 во входных данных. Это верно? –

+0

И какая версия MS SQL Server? 2005 и 2008 доступны инструменты, чтобы сделать это проще, чем 2000 нет. –

ответ

1

кажется мне, как вам нужно что-то вроде этого:

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

Является ли это запрос запуска?

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) 

Если у вас есть индекс по (make, model, driverid, distance), это один может быть более эффективным:

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

Вы явно хотите сохранить путешествия отдельно - результаты, которые вы говорите, вы хотите, например, дл драйвер 401 включает в себя первую строку, затем min/max запускается по второму набору строк для этого драйвера. Таким образом, похоже, что у вас отсутствует столбец «JourneyID» или аналогичный. Первая строка будет иметь одно значение для JourneyID, второй набор строк будет иметь одно значение JourneyID, но отличается от первого для первой строки.

Если у вас есть этот столбец, вы можете добавить его в предложение Group By.

0

Решение MS SQL 2005/2008. Не будет работать на 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