从1个表中的多个行中选择值作为1个记录

时间:2014-07-04 07:05:49

标签: sql sql-server sql-server-2008

我很难解释我需要做什么,所以请耐心等待我。 我有下表和行:

TBNAME: Distances

跟踪,人员,日期,距离

TRACK1, P1, 1/1/2014, 15
TRACK2, P1, 13/1/2014, 12
TRACK1, P1, 20/2/2014, 10
TRACK2, P1, 15/1/2014, 9
TRACK1, P2, 2/1/2014, 11
TRACK2, P2, 14/1/2014, 13
TRACK1, P2, 21/2/2014, 8
TRACK2, P2, 16/1/2014, 6

理想情况下,我希望看到结果是这样的:

P1, TRACK1, 20/2/2014, 10, TRACK2, 15/1/2014, 9
P2, TRACK1, 21/2/2014, 8, TRACK2, 16/1/2014, 6

或者换句话说,对于每个人,一行中每个曲目的最近日期和距离。

希望有人能理解这一点并提供解决方案:)

干杯, 皮尔

8 个答案:

答案 0 :(得分:0)

尝试单独组合表并将它们与公共列连接。

在您的情况下,您需要Person

Select t1.Person, 
       t1.Tract, 
       t1.Date, 
       t1.Distance,
       t2.Tract, 
       t2.date, 
       t2.Distance 
From table_name t1, table_name t2
WHERE t1.Person = t2.Person;

答案 1 :(得分:0)

试试这个:

SELECT DISTINCT ON ("Person", "Track") *
FROM   "Table"
ORDER  BY "Person", "Date" DESC NULLS LAST;

答案 2 :(得分:0)

寻找ROW_NUMBER()OVER PARITION BY

Idea就像(我没有尝试运行此查询):

;WITH
  data AS
  (
    SELECT
      *,
      -- returns number for each pair of person and track starting from most recent date
      --Code enhanced at here
      row_number() over (partition BY person, track order by dte DESC) nr 
    FROM distances
  ) 
  SELECT
    *
  FROM
    data
  WHERE
    nr = 1 -- we want just the most recent one
  ORDER BY
    person, -- "group by" person
    track ;

它仍然不支持为每个人显示一行...... 我不认为你可以使用SQL(因为轨道数量未知)。

PIVOT/UNPIVOT,但我认为不适合这里。

答案 3 :(得分:0)

这是一个获取所需记录的查询。首先获得每个曲目和人的最大日期。然后加入表格以获得完整的记录。

如果您事先知道将获得哪些曲目,则可以使用数据透视查询。由于我从未这样做过,我请你自己查一下。但是,正如我对您的请求的评论中所提到的,我会使用编程语言(C#,Java,PHP或其他)来关注它。

select d.track, d.person, d.date, d.distance
from
(
  select track, person, max(distances.date) as `date`
  from distances
  group by track, person
) lastd
inner join distances d on d.track = lastd.track and d.person = lastd.person and d.date = lastd.date
order by d.track, d.person;

BTW:date是保留关键字。我不建议将它用于列名。无论何时使用它而没有限定符,您都必须使用这些奇怪的引号。

答案 4 :(得分:0)

试试这个:

SELECT    T1.Person, T1.Track, MAX(T1.Date), MIN(T1.Distance), 
          T2.Track, MAX(T2.Date), MIN(T2.Distance)
FROM      Distances AS T1 INNER JOIN
          Distances AS T2 ON T1.Person = T2.Person
WHERE     T1.Track <> T2.Track AND T1.Track = 'Track1'
GROUP BY  T1.Track, T1.Person, T2.Track

查询的输出结果与预期结果完全相同。

答案 5 :(得分:0)

WITH CTE AS 
(
Select P1.Track,P1.Person,ROW_NUMBER() OVER (Partition by Person,Track Order by Date         

Desc) AS RN1 
,Date,Distance
from Distances P1
)Select T.Person,T.Track1,T.T1Date
,T.T1Distance,T.Track2,T.T2Date,T.T2Distance 
From (
Select C1.Person,C1.Track AS 'Track1',C1.Date AS 'T1Date',
C1.Distance 'T1Distance', 
C2.Track AS 'Track2',C2.Date As 'T2Date',C2.Distance 'T2Distance',
ROW_NUMBER() OVER (Partition BY C1.Person Order by C1.Date Desc) RNX 
from 
CTE C1 
JOIN 
CTE C2 ON C1.RN1=1 AND C2.RN1=1
AND C1.Person=C2.Person
AND C1.Track<>C2.Track
)t Where t.RNX=1

答案 6 :(得分:0)

要获得一般查询,它需要是动态的

DECLARE @query AS NVARCHAR(MAX)
DECLARE @pivotCols AS NVARCHAR(MAX)
DECLARE @cols AS NVARCHAR(MAX)

SELECT @pivotCols = STUFF((SELECT DISTINCT ',' + QUOTENAME([Track])
                      FROM Distances
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') , 1, 1, '')
;WITH T AS (
  SELECT Track
       , _ID = CAST(Row_Number() OVER (ORDER BY Track) AS VARCHAR)
  FROM   Distances
  GROUP BY Track
)
SELECT @Cols = STUFF((
       SELECT ', Track_' + _ID + ' = ''' + Track + ''''
            + ', LastRun_' + _ID + ' = ' + QUOTENAME([Track])
            + ', Distance_' + _ID + ' 
               = SUM(CASE WHEN d.Date = ' + QUOTENAME([Track]) + ' 
                           AND d.Track = ''' + Track + ''' 
                          THEN d.Distance ELSE NULL END)'
                      FROM T FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') , 1, 1, '')
SELECT @query = '
With LR AS (
  SELECT Person, ' + @pivotCols + '
  FROM   (SELECT Track, Person, [Date] FROM   Distances) d
         PIVOT (MAX([Date]) FOR Track IN (' + @pivotCols + ')) pvt
)
SELECT d.Person, ' + @Cols + '
FROM   Distances d
       INNER JOIN LR ON d.Person = LR.Person AND d.Date IN (' + @pivotCols + ')
GROUP BY d.Person, ' + @pivotCols + ''

execute(@query);

SQLFiddle demo

第一个查询生成PIVOT的字段列表 第二个生成复合查询的字段。

PIVOT用于为每个人获取每个轨道上的最后一次运行,然后将其连接回基础数据以获得距离

答案 7 :(得分:0)

您也可以使用动态查询来达到预期的效果:)

DECLARE @nCount INT 
DECLARE @nStart INT
DECLARE @Query NVARCHAR(MAX) =' '
DECLARE @sPerson NVARCHAR(MAX)
DECLARE @sTrack NVARCHAR(MAX)

SET @nCount = (SELECT COUNT(DISTINCT(person)) FROM DISTANCES)

SET @nStart = 1

WHILE @nStart <= @nCount
BEGIN

SET @sPerson = (SELECT PERSON FROM (
SELECT PERSON, ROW_NUMBER() OVER (ORDER BY PERSON) RN FROM (
SELECT DISTINCT(PERSON) FROM DISTANCES
) T1 
) T2 WHERE RN = @nStart
)


SET @Query = @Query + ' 
SELECT '''+@sPerson+''' + '','' + STUFF( '','' +(
SELECT TRACK + '', '' + DATE + '', '' + DISTANCE FROM (
SELECT TRACK, DATE,DISTANCE, 
ROW_NUMBER() OVER (PARTITION BY TRACK ORDER BY DATE DESC) RN FROM (
SELECT TRACK,date,DISTANCE FROM DISTANCES WHERE PERSON = '''+@sPerson+'''
) T1 
) T2
WHERE RN = 1 FOR XML PATH('''')
),1,1,''''
)
'
IF(@nStart != @nCount)
SET @Query = @Query + ' UNION ALL '

SET @nStart = @nStart + 1

END

EXEC SP_EXECUTESQL @Query