我的MS SQL表中有一组记录。使用Date作为主键。但是日期只适用于工作日,而不是持续的日子。例如:
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 AM 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的值减去前一个工作日的第3列的值。请帮我写这样的查询。我发现这很困难,因为本周结束时没有日期。
答案 0 :(得分: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
答案 1 :(得分:1)
您需要将其分为两部分。首先是更新现有数据,其次是确保所有新数据都添加了正确的值。
对于第一部分,请考虑使用CURSOR。它可能需要一段时间才能运行,但至少你只运行一次。像FOR循环一样使用CURSOR;遍历数据中的每一行,忽略第一行(因为您没有指定在没有上一个日期时如何计算新列的值)。最有可能你应该按日期升序排序,以防万一。
在迭代时,使用变量存储此行的值。在循环时,在获得新行之前将这些变量复制到先前的行版本中。例如,您有一个名为'Col3'的变量,另一个名为'lastCol3'。在循环到下一行之前(即光标移动到下一行),将col3的值复制到lastCol3中,然后获取col3的新值。现在,您可以按行获得当前和之前的值,并可以调用“更新”来更新新列。
对于新数据,您需要确保提供新值,或者如果您希望SQL Server执行此操作,请使用选择最新行col3的存储过程,并使用该值计算新值插入表格之前的值。
答案 2 :(得分:1)
使用自连接和case语句,利用SQLServers的内置日期函数datepart(dw,@Date)
。
我确实有责任注意到,首先进行这样的转变可能是一个坏主意。