Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何分配以前的日期?_Sql_Sql Server_Tsql - Fatal编程技术网

Sql 如何分配以前的日期?

Sql 如何分配以前的日期?,sql,sql-server,tsql,Sql,Sql Server,Tsql,表A 当id=2时,我想分配e_dt=2018-01-06(即id=10的st_dt前一天) 如何做到这一点?您需要一条记录中两条记录的信息,请先按CTE和ROW_编号的顺序准备,然后将结果本身连接起来,以按顺序排列一条记录和下一条记录: +====+======+============+============+ | id | m_id | s_dt | e_dt | +====+======+============+============+ | 2 | 10

表A

id=2
时,我想分配
e_dt=2018-01-06
(即
id=10的
st_dt
前一天)


如何做到这一点?

您需要一条记录中两条记录的信息,请先按CTE和ROW_编号的顺序准备,然后将结果本身连接起来,以按顺序排列一条记录和下一条记录:

+====+======+============+============+
| id | m_id |    s_dt    |    e_dt    |
+====+======+============+============+
|  2 |  101 | 2015-06-28 | 2059-12-31 |
+----+------+------------+------------+
| 10 |  101 | 2018-01-07 | 2059-12-31 |
+----+------+------------+------------+

如果您使用的是SQL Server 2012或更高版本,可以尝试以下操作:

with TA as
(select ROW_NUMBER() over(order by id) as rn,* from TableA)
select t1.id,t1.m_id,t1.s_dt,DATEADD(day, -1,t2.st_dt) as e_dt 
from TA t1 join TA t2 on t1.rn+1=t2.rn

为此,我建议使用,例如:

SELECT id, s_dt , DATEADD(DAY,-1,LEAD(s_dt) OVER(ORDER BY id)) AS e_dt FROM YourTable
在我的示例中,您将看到,
e_dt
当它是对应的
m_id
的最后一行/最近一行时,将是您的未来日期
2059-12-31
,因为还没有对应的
s_dt
的行。根据列的命名方式,基本上我要说的是“这个
m_id
的当前运行没有“结束日期”,但它仍然在运行”

此外,您将看到,即使数据以非顺序插入到表中,这种方法仍然有效。也就是说,具有不同值的
m_id
可以很好地插入到另一个
m_id
的一对开始日期和结束日期之间

测试结果:

代码I用于测试,带有附加测试值:

--use common table expression to sort the m_id and id into unique row numbers
;WITH cte
AS (
    SELECT ROW_NUMBER() OVER (ORDER BY m_id, id) AS rowNum
    , *
    FROM TableA
    )
--Update the original table, using the row number + 1 
--(use the next row to determine the next s_dt) 
UPDATE tblA
SET tblA.e_dt = DATEADD(day, - 1, tblB.s_dt)
FROM cte tblA
INNER JOIN cte tblB ON tblA.rowNum + 1 = tblB.rowNum and tblA.m_id = tblB.m_id

再添加几行示例表数据及其预期结果。@user3183055我在提供的答案中输入了更多示例数据。如果需要进行调整,请告诉我。@user3183055-再次您好!如果你在这里发现了一个有用的答案,请不要忘记接受一个并投票支持它。这样做,你和他们都获得了积极的声誉,这有助于未来的访问者确定哪个答案是最合适/最有帮助的答案。如果您对此有任何疑问,请查看此链接:感谢您提供此代码段,它可能会提供一些有限的即时帮助。A通过展示为什么这是一个很好的解决问题的方法,并将使它对未来有其他类似问题的读者更有用。请在您的回答中添加一些解释,包括您所做的假设。@iBug;谢谢你的评论。
CREATE TABLE [dbo].[TableA](
    [ID] [INT] IDENTITY(1,1) NOT NULL,
    [m_id] [INT],
    [s_dt] [DATETIME],
    [e_dt] [DATETIME]
 CONSTRAINT [PK_TableA_ID] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
) ON [PRIMARY]
GO


INSERT INTO [dbo].[TableA]
SELECT '101','2015-06-28','2059-12-31' UNION ALL
SELECT '101','2018-01-07','2059-12-31' UNION ALL
SELECT '102','2015-06-28','2059-12-31' UNION ALL
SELECT '102','2016-05-07','2059-12-31' UNION ALL
SELECT '103','2015-06-28','2059-12-31' UNION ALL
SELECT '103','2017-01-07','2059-12-31' UNION ALL
SELECT '102','2017-05-28','2059-12-31' UNION ALL
SELECT '104','2018-01-07','2059-12-31' UNION ALL
SELECT '103','2018-01-07','2059-12-31' UNION ALL
SELECT '102','2018-06-28','2059-12-31' UNION ALL
SELECT '104','2018-01-24','2059-12-31'
GO

--verify data
SELECT * FROM TableA

--use common table expression to sort the m_id and id into unique row numbers
;WITH cte
AS (
    SELECT ROW_NUMBER() OVER (ORDER BY m_id, id) AS rowNum
    , *
    FROM TableA
    )
--Update the original table, using the row number + 1 (use the next row to determine the next s_dt) 
UPDATE tblA
SET tblA.e_dt = DATEADD(day, - 1, tblB.s_dt)
FROM cte tblA
INNER JOIN cte tblB ON tblA.rowNum + 1 = tblB.rowNum and tblA.m_id = tblB.m_id

--verify
SELECT * FROM TableA ORDER BY m_id, id


--DROP TABLE dbo.[TableA]