2009-02-03 2 views
2

У меня есть набор записей в моей таблице MS SQL. С Date в качестве основного ключа. Но Даты только для рабочих дней, а не для продолжительных дней. Например:Как получить следующую запись в таблице SQL

1/3/2000 12:00:00 AM 5209,540000000 5384,660000000 5209,540000000 5375,110000000 1/4/2000 12:00:00 AM 5533,980000000 5533,980000000 5376,430000000 5491,010000000 1/5/2000 12:00:00 AM +5265,090000000 5464,350000000 5184,480000000 5357,000000000 1/6/2000 12:00:00 AM 5424,210000000 5489,860000000 5391,330000000 5421,530000000 1/7/2000 12:00:00 AM 5358,280000000 5463,250000000 5330,580000000 5414,480000000 1/10/2000 12:00:00 AM +5617,590000000 5668,280000000 5459,970000000 5518.390000000 1/11/2000 12:00:00 утра 5513.040000000 5537.690000000 5221.280000000 5296.300000000 1/12/2000 12:00:00 AM 5267.850000000 5494.300000000 5267.850000000 5491.200000000

В этом я пытаюсь ввести новый столбец в таблицу, а значение для него должно быть значением 3-го cloumn минус значение третьего столбца предыдущего рабочего дня. Пожалуйста, помогите мне написать такой запрос. Мне трудно, потому что даты нет для окончания недели.

ответ

2

Есть несколько способов сделать это. Вот один.

CREATE TABLE MyTable 
(
    MyDate datetime NOT NULL PRIMARY KEY, 
    Col2 decimal(14,4) NOT NULL, 
    Col3 decimal(14,4) NOT NULL, 
    Col4 decimal(14,4) NOT NULL, 
    Col5 decimal(14,4) NOT NULL 
) 
GO 

INSERT INTO MyTable 
SELECT '1/3/2000 12:00:00 AM', 5209.540000000, 5384.660000000, 5209.540000000, 5375.110000000 
UNION ALL 
SELECT '1/4/2000 12:00:00 AM', 5533.980000000, 5533.980000000, 5376.430000000, 5491.010000000 
UNION ALL 
SELECT '1/5/2000 12:00:00 AM', 5265.090000000, 5464.350000000, 5184.480000000, 5357.000000000 
UNION ALL 
SELECT '1/6/2000 12:00:00 AM', 5424.210000000, 5489.860000000, 5391.330000000, 5421.530000000 
UNION ALL 
SELECT '1/7/2000 12:00:00 AM', 5358.280000000, 5463.250000000, 5330.580000000, 5414.480000000 
UNION ALL 
SELECT '1/10/2000 12:00:00 AM', 5617.590000000, 5668.280000000, 5459.970000000, 5518.390000000 
UNION ALL 
SELECT '1/11/2000 12:00:00 AM', 5513.040000000, 5537.690000000, 5221.280000000, 5296.300000000 
UNION ALL 
SELECT '1/12/2000 12:00:00 AM', 5267.850000000, 5494.300000000, 5267.850000000, 5491.200000000 
GO 

CREATE VIEW MyView 
AS 
SELECT T1.*, 
    CalculatedColumn = Col3 - 
     (SELECT Col3 FROM MyTable Q2 
     WHERE Q2.MyDate = (SELECT MAX(Q1.MyDate) 
          FROM MyTable Q1 
          WHERE Q1.MyDate < T1.MyDate) 
    ) 
FROM MyTable T1 
GO 

SELECT * FROM MyView 
GO 

Результаты

MyDate     Col2  Col3  Col4  Col5  CalculatedColumn 
----------------------- --------- --------- --------- --------- ---------------- 
2000-01-03 00:00:00.000 5209.5400 5384.6600 5209.5400 5375.1100 NULL 
2000-01-04 00:00:00.000 5533.9800 5533.9800 5376.4300 5491.0100 149.3200 
2000-01-05 00:00:00.000 5265.0900 5464.3500 5184.4800 5357.0000 -69.6300 
2000-01-06 00:00:00.000 5424.2100 5489.8600 5391.3300 5421.5300 25.5100 
2000-01-07 00:00:00.000 5358.2800 5463.2500 5330.5800 5414.4800 -26.6100 
2000-01-10 00:00:00.000 5617.5900 5668.2800 5459.9700 5518.3900 205.0300 
2000-01-11 00:00:00.000 5513.0400 5537.6900 5221.2800 5296.3000 -130.5900 
2000-01-12 00:00:00.000 5267.8500 5494.3000 5267.8500 5491.2000 -43.3900 
+0

Возможно, вы можете оптимизировать предложение innermost where, чтобы ограничить, какие строки в Q1 будут проверены. Вы знаете, что предыдущая строка будет на 2 или 3 дня раньше. –

+0

@Mike Он выполняет CLUSTERED INDEX SEEK, что очень эффективно. SQL Server, как правило, очень хорош в самооптимизации. – beach

1

Вам необходимо разбить его на 2 части. Сначала обновляем существующие данные, а во-вторых, все новые данные имеют правильную добавленную стоимость.

Для первой части рассмотрите использование КУРСОРА. Для запуска, вероятно, потребуется некоторое время, но, по крайней мере, вы запускаете его только один раз. Используйте КУРСОР как цикл FOR; итерации по каждой строке в ваших данных, игнорируя первую строку (поскольку вы не указали, как вычислить значение для нового столбца, когда нет предыдущей даты). Скорее всего, вы должны сортировать по дате по возрастанию, на всякий случай.

Как вы итерируете, используйте переменные для хранения значений из этой строки. Когда вы зацикливаете, скопируйте эти переменные в предыдущие версии строк, прежде чем вы получите новую строку. Например, у вас есть переменная, называемая «Col3», а другая - «lastCol3». Прежде чем вы перейдете к следующей строке (т.е. курсор переместится к следующей строке), вы скопируете значение col3 в lastCol3, а затем получите новое значение для col3. Теперь у вас есть текущее и предыдущее значение для каждой строки, и вы можете вызвать «обновление», чтобы обновить новый столбец.

Для ввода новых данных необходимо обеспечить новое значение или если SQL Server должен сделать это, используйте хранимую процедуру, которая выбирает самую последнюю строку col3, и использует значение для вычисления новое значение перед вставкой в ​​таблицу.

1

Использование автообъединения и саз, что использует SQLServers встроенных в функции даты datepart(dw,@Date).

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