SQL-запрос для верхнего и нижнего значения для конкретной даты - PullRequest
0 голосов
/ 10 июня 2009

SQL Server 2000

Мой стол:

CARDNO  CARDEVENTDATE   CARDEVENTTIME
121 20090610    025050
 121    20090611    040000
121 20090611    050000
121 20090611    020000
122 20090611    030001
122 20090611    030000
123 20090611    080000
123 20090611    100000
123 20090611    132449
123 20090611    025959
124 20090610    030000
124 20090612    030001
125 20090611    030002
125 20090612    040000

Cardno - отдельный стол Cardeventdate, cardeventtime - это отдельный стол

Из приведенной выше таблицы я хочу получить верхнее и нижнее время для конкретного события cardeventdate и Cardno

Для 121, 20090611, верхнее время - 040000, нижнее время - 020000 Для 123, 20090611, верхнее время - 080000, нижнее время - 025959… Как это мне нужно.

Я использовал Мин (время) и Макс (время), но он показывал вот так.

Для CardNo - 121 Cardeventdate - 20090611 Минимальное время - 020000 Максимальное время - 040000

Я не хочу получать min и Max, мне нужны только значения top и Bottom (или) First and Last time конкретной даты и Cardno.

Я использовал этот запрос

SELECT     RowNumber = IDENTITY (int, 1, 1), CARDNO, CARDEVENTDATE, CARDEVENTTIME INTO #Table1 FROM T_CARDEVENT SELECT     t1.CARDNO, t1.CARDEVENTDATE, t1.CARDEVENTTIME  FROM #Table t1 INNER JOIN (SELECT     RowNumber = MIN(RowNumber), CARDEVENTDATE, CARDNO  FROM  #Table1 t  WHERE      (cardeventdate > 20090601) GROUP BY cardno, cardeventdate  UNION ALL  SELECT     MAX(RowNumber), CARDEVENTDATE, CARDNO FROM #Table1 t WHERE     (cardeventdate > 20090601) GROUP BY cardno, cardeventdate) t2 ON t2.rownumber = t1.rownumber

Выход:

ROWNUMBER   CARDNO  CARDEVENTDATE   CARDEVENTTIME
335 0121               20090611     040000
1099    0121               20090611     050000
1100    0121               20090611     025050
336 0121               20090612     020000
337 0122               20090611     030001
338 0122               20090612     030000
339 0123               20090611     080000
1101    0123               20090611     100000
1102    0123               20090611     132449
340 0123               20090612     025959
341 0124               20090611     030000
342 0124               20090612     030001
343 0125               20090611     030002
344 0125               20090612     040000

Итак, номер строки создается для всех столбцов, исходя из того, как я должен использовать Первый раз и Последний раз для конкретной даты.

Ожидаемый вывод

CARDNO  CARDEVENTDATE   CARDEVENTTIME   Expecting
0121    20090611    040000  Top Value
0121    20090611    020000  No Need
0121    20090611    025050  Bottom Value

……… так далее

Нужна справка по запросу.

Ответы [ 5 ]

5 голосов
/ 10 июня 2009

Ну, если у вас нет дополнительных полей для установки порядка, это недетерминировано. Учитывая три значения для 23-04-2009 - как получается, что APPLE является первым, а ROSE - последним? Если идентификатор и ДАТА одинаковы для всех трех записей, не определен порядок для фильтрации «GRAPHE» ......

Марк

ОБНОВЛЕНИЕ: Я немного расширил идею Ливена, и у меня все получилось:

DECLARE @TempTable TABLE (RowNumber INT IDENTITY(1,1), 
                          DayNumber INT, 
                          ID VARCHAR(3), DateField DATETIME, Value VARCHAR(32))

INSERT INTO @TempTable(DayNumber, id, datefield, value)
    SELECT DATEPART(DAYOFYEAR, DateField), ID, DateField, Value
    FROM @Table

SELECT * 
FROM @TempTable t
INNER JOIN 
   (SELECT RowNumber = MIN(RowNumber), DayNumber, ID
    FROM @TempTable t
    GROUP BY DayNumber, t.ID
    UNION ALL 
    SELECT MAX(RowNumber), DayNumber, ID
    FROM @TempTable t
    GROUP BY DayNumber, t.ID) t2 
  ON t2.RowNumber = t.RowNumber
GO

Я в основном создаю временную таблицу с дополнительной информацией - искусственный «RowNumber» для создания некоторого заказа и «DayNumber» для получения дат, сгруппированных только по дате (без времени).

Кажется, у меня все в порядке - у вас тоже работает?

1 голос
/ 10 июня 2009

Jash, если вы запустите этот скрипт, он даст вам ожидаемые результаты?

CREATE TABLE #T_Cardevent (CARDNO VARCHAR(3), CARDEVENTDATE VARCHAR(8), CARDEVENTTIME VARCHAR(8))

INSERT INTO #T_Cardevent VALUES ('121', '20090610', '025050')
INSERT INTO #T_Cardevent VALUES ('121', '20090611', '040000')
INSERT INTO #T_Cardevent VALUES ('121', '20090611', '050000')
INSERT INTO #T_Cardevent VALUES ('121', '20090611', '020000')
INSERT INTO #T_Cardevent VALUES ('122', '20090611', '030001')
INSERT INTO #T_Cardevent VALUES ('122', '20090611', '030000')
INSERT INTO #T_Cardevent VALUES ('123', '20090611', '080000')
INSERT INTO #T_Cardevent VALUES ('123', '20090611', '100000')
INSERT INTO #T_Cardevent VALUES ('123', '20090611', '132449')
INSERT INTO #T_Cardevent VALUES ('123', '20090611', '025959')
INSERT INTO #T_Cardevent VALUES ('124', '20090610', '030000')
INSERT INTO #T_Cardevent VALUES ('124', '20090612', '030001')
INSERT INTO #T_Cardevent VALUES ('125', '20090611', '030002')
INSERT INTO #T_Cardevent VALUES ('125', '20090612', '040000')

SELECT     
  RowNumber = IDENTITY (int, 1, 1)
  , CARDNO
  , CARDEVENTDATE
  , CARDEVENTTIME 
INTO #Table
FROM #T_CARDEVENT 

SELECT t1.CARDNO, t1.CARDEVENTDATE, t1.CARDEVENTTIME  
FROM #Table t1 
     INNER JOIN (
        SELECT RowNumber = MIN(RowNumber), CARDEVENTDATE, CARDNO 
        FROM #Table t  
        GROUP BY cardno, cardeventdate  
        UNION ALL SELECT MAX(RowNumber), CARDEVENTDATE, CARDNO 
        FROM #Table t 
        GROUP BY cardno, cardeventdate) t2 ON t2.rownumber = t1.rownumber
ORDER BY 1, 2, 3

DROP TABLE #Table
DROP TABLE #T_Cardevent
0 голосов
/ 10 июня 2009

Вот решение с использованием встроенных представлений:

with 
tempFirst as (
    select id, date, value, 
     row_number() over (partition by id, date order by date asc) as rownum1
    from table1
),
tempLast as ( 
    select *, 
     row_number() over (partition by id, date order by rownum1 desc) as rownum2 
    from tempFirst
)
select id, date, value from tempFirst where rownum1 = 1
union
select id, date, value from tempLast where rownum2 = 1

Я протестировал вывод:

ID  DATE       VALUE
001 2009-04-23 APPLE
001 2009-04-23 ROSE
001 2009-04-24 BERRY
001 2009-04-24 SILVER
0 голосов
/ 10 июня 2009

для обмана вы можете добавить поле автонумерации AUtoID ID ДАТА ЗНАЧЕНИЕ 1 001 23: 04: 2009 ЯБЛОКО 2 001 23: 04: 2009 ГРАФ 3 001 23: 04: 2009 РОЗА 4 001 24: 04: 2009 ЯГОДА 5 001 24: 04: 2009 TIFFANY 6 001 24: 04: 2009 ОРГАН 7 001 24: 04: 2009 СЕРЕБРО

Вы можете сделать мин и макс против него

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

0 голосов
/ 10 июня 2009

Я не пробовал, но, может быть, что-то подобное может сделать это:

SELECT TOP(1) FROM Table
WHERE Date='Some-date'
AND Id=Some-Id
ORDER BY Date ASC
UNION
SELECT TOP(1) FROM Table
WHERE Date='Some-date'
AND Id=Some-Id
ORDER BY Date Desc
...