Как я могу выбрать отдельные данные на основе поля даты? - PullRequest
2 голосов
/ 26 мая 2011

У меня есть таблица, в которой хранится журнал изменений объектов в другой таблице. Вот мое содержание таблицы:

ObjID   Color   Date                     User
------- ------- ------------------------ --------
1       Red     2010-01-01 12:22:00.000  Joe
1       Blue    2010-01-02 15:22:00.000  Jill
1       Green   2010-01-03 16:22:00.000  Joe
1       White   2010-01-10 09:22:00.000  Mike
2       Red     2010-01-09 10:22:00.000  Mike
2       Blue    2010-01-12 09:22:00.000  Jill
2       Orange  2010-01-12 15:22:00.000  Joe

Я хочу выбрать самую последнюю дату для каждого объекта, а также цвет и пользователя на дату этой записи.

В принципе, я хочу этот набор результатов:

ObjID   Color   Date                     User
------- ------- ------------------------ --------
1       White   2010-01-10 09:22:00.000  Mike
2       Orange  2010-01-12 15:22:00.000  Joe

У меня проблемы с наведением головы на SQL-запрос, который мне нужно написать, чтобы получить эти данные ...

Я получаю данные через ODBC из базы данных DB2 iSeries (AS / 400).

Ответы [ 7 ]

4 голосов
/ 26 мая 2011

Привет, я думаю, вы хотите следующее (где ColorTable - это имя вашей таблицы):

SELECT Color.* 
FROM ColorTable as Color
INNER JOIN 
(
SELECT ObjID, MAX(Date) as Date
FROM ColorTable
GROUP BY ObjID
) as MaxDateByColor
ON Color.ObjID = MaxDateByColor.ObjID
AND Color.Date = MaxDateByColor.Date 
3 голосов
/ 26 мая 2011

Предполагается, по крайней мере, SQL Server 2005

DECLARE @T TABLE (ObjID INT,Color VARCHAR(10),[Date] DATETIME,[User] VARCHAR(50))

INSERT INTO @T
SELECT 1,'Red',' 2010-01-01 12:22:00.000','Joe' UNION ALL
SELECT 1,'Blue','2010-01-02 15:22:00.000','Jill' UNION ALL
SELECT 1,'Green',' 2010-01-03 16:22:00.000','Joe' UNION ALL
SELECT 1,'White',' 2010-01-10 09:22:00.000','Mike' UNION ALL
SELECT 2,'Red',' 2010-01-09 10:22:00.000','Mike' UNION ALL
SELECT 2,'Blue','2010-01-12 09:22:00.000','Jill' UNION ALL
SELECT 2,'Orange','2010-01-12 15:22:00.000','Joe'

;WITH T AS
(
SELECT *,
       ROW_NUMBER() OVER (PARTITION BY ObjID ORDER BY Date DESC) AS RN
FROM @T
)
SELECT ObjID,
       Color,
       [Date],
       [User]
FROM T 
WHERE RN=1

Или метод SQL Server 2000 из статьи, ссылки на которую есть в комментариях

SELECT ObjID,
  CAST(SUBSTRING(string, 24, 33) AS VARCHAR(10)) AS Color,
  CAST(SUBSTRING(string,  1, 23) AS DATETIME ) AS [Date],
  CAST(SUBSTRING(string, 34, 83) AS  VARCHAR(50)) AS [User]
FROM 
(
SELECT ObjID, 
          MAX((CONVERT(CHAR(23), [Date], 126)
         + CAST(Color AS CHAR(10))
         + CAST([User] AS CHAR(50))) COLLATE Latin1_General_BIN) AS string
FROM @T
GROUP BY ObjID) T;
1 голос
/ 26 мая 2011

Если у вас есть таблица Objects, а ваша таблица ObjectHistory имеет индекс ObjID и дату, то это может работать лучше, чем другие запросы, приведенные до сих пор:

SELECT
   X.*
FROM
   Objects O
   CROSS APPLY (
      SELECT TOP 1 *
      FROM ObjectHistory H
      WHERE O.ObjID = O.ObjID
      ORDER BY H.[Date] DESC
   ) X

Повышение производительности может произойти только в том случае, если выВы тоже вытаскиваете столбцы из таблицы Объектов, но это стоит того.

Если вы хотите, чтобы все Объекты независимо от того, имеют ли они запись в истории, переключитесь на OUTER APPLY (и, конечно, используйте O.ObjIDвместо H.ObjID).

Изюминкой этого запроса является то, что

  1. Он решает ситуации, в которых значение Date может иметь дубликаты
  2. Может поддерживатьпроизвольное количество элементов в группе (скажем, топ-5 вместо топ-1)
0 голосов
/ 22 октября 2014

как и выше Мартин Смитс, просто сделайте номер строки над разделом и выберите одну из последних строк, например

SELECT  Color,Date,User
FROM (
   SELECT *,
          ROW_NUMBER() OVER (PARTITION BY User ORDER BY [DATE]) AS ROW_NUMBER
   FROM [tablename]
   ) AS ROWS
WHERE 
ROW_NUMBER = 2
0 голосов
/ 26 мая 2011

Для каждого объекта вы можете узнать его самое последнее изменение, например:

        select objectid, max(changedate) as LatestChange
        from LOG
        group by objectid

Затем вы можете получить цвет и пользовательские столбцы, связав набор, возвращенный выше, созданный в виде встроенного представления, имеющегополучил псевдоним, снова к той же таблице:

       select color, user, FOO.objectid, FOO.LatestChange
       from LOG
       inner join
       (

          select objectid, max(changedate) as LatestChange
        from LOG
        group by objectid


        ) as FOO
        on LOG.objectid = FOO.objectid and LOG.changedate = FOO.LatestChange
0 голосов
/ 26 мая 2011
SELECT t1.* FROM Table_name as t1
INNER JOIN (
  SELECT MAX(Date) as MaxDate, ObjID FROM Table_name
  GROUP BY ObjID
) as t2
ON t1.ObjID = t2.ObjID AND t1.Date = t2.MaxDate
...