如何在 SQL SERVER 2017 SSMS 中用以前保存的行值替换行值
Posted
技术标签:
【中文标题】如何在 SQL SERVER 2017 SSMS 中用以前保存的行值替换行值【英文标题】:How to replace row value with previous saved row value in SQL SERVER 2017 SSMS 【发布时间】:2019-08-13 06:13:43 【问题描述】:首先我的问题太复杂了,抱歉我的英语不好
所以,我在 SQL 中得到了一些表值函数查询,以便为我在 VB 上选择的每一天自动生成 5 行
这里是这个表值函数如何在 2 天内工作的示例
列数量的默认值为每次 1
默认名称始终为 A , B , C , D , E
它将每天生成新的 5 行,然后上面的所有数据将使用存储过程 (tblProduce) 提交到另一个表中 图片中的所有列都来自VB DataViewGrid,我只制作表值函数来获取ID、名称。其余部分将在VB上填写
主要问题:
我想要的是,如果我在 2019 年 7 月 25 日创建并保存此数据并将 CheckBox 的行值之一更改为 True
然后,第二天,当我想创建另一个数据时,应该是这样的 这是预期的数据应该在第 2 天
绿色背景表示当复选框 = True 时,数据取自上次保存的行
这是针对 SSMS SQL Server 2017 的,我已经尝试在表值函数上使用 UNION
/ SUB QUERY 但仍然没有弄清楚如何做这件事
QUERY 获取选择了多少天:
CREATE FUNCTION [dbo].[tvfCustomDateRange] (@Increment char(1), @StartDate date, @EndDate date)
RETURNS @SelectedRange TABLE (cDate date)
AS
BEGIN
;WITH cteRange (DateRange) AS (
SELECT @StartDate
UNION ALL
SELECT
CASE
WHEN @Increment = 'd' THEN DATEADD(dd, 1, DateRange)
WHEN @Increment = 'w' THEN DATEADD(ww, 1, DateRange)
WHEN @Increment = 'm' THEN DATEADD(mm, 1, DateRange)
END
FROM cteRange
WHERE DateRange <=
CASE
WHEN @Increment = 'd' THEN DATEADD(dd, -1, @EndDate)
WHEN @Increment = 'w' THEN DATEADD(ww, -1, @EndDate)
WHEN @Increment = 'm' THEN DATEADD(mm, -1, @EndDate)
END)
INSERT INTO @SelectedRange (cDate)
SELECT DateRange
FROM cteRange
OPTION (MAXRECURSION 3660);
RETURN
END
我在 vb 上选择的每隔多少天生成第 5 行的查询是:
CREATE FUNCTION [dbo].[tvfGenerate5Row] (@BeginDate DateTimeOffset, @EndDate Datetimeoffset)
RETURNS TABLE
AS
RETURN
(
SELECT IsNuLL(tblProduce.Idtbl5Row,tblCustom.Idtbl5Row),
IsNULL(tblProduce.Name,tblCustom.Name),
IsNULL(tblProduce.Quantity,1),
IsNULL(tblProduce.cDate,tblCustom.cDate),
IsNULL(tblProduce.CheckBox,'')
FROM (SELECT Name, cDate, Idtbl5Row
FROM tvfCustomDateRange('d', @BeginDate, @EndDate) CROSS JOIN tblWith5Row) AS tblCustom LEFT OUTER JOIN tblProduce ON tblCustom.cDate=tblProduce.cDate
)
CREATE TABLE tblProduce
(
IdtblProduce BigInt Primary Key,
Idtbl5Row BigInt,
Name VarChar(25),
Quantity Integer,
cDate DateTime,
CheckBox Bit,
FOREIGN KEY (Idtbl5Row) REFERENCES tblWith5Row(Idtbl5Row)
)
【问题讨论】:
你的预期输出是什么 第一数据图片和第二数据图片tableWith5Row
这是什么表。以及其中存在的数据。
它唯一的5行数据只有ID和名称属性gyazo.com/551c9dc60720244c140babd760c0e28a这样
究竟在哪个表中保存了一天的数据,就像你标记了true
,然后这个true
的条目被保存在特定日期的哪个表中。
【参考方案1】:
因为您的表中已经有这 5 行。现在每次您只想输入相同的新日期,所以最好使用以前的日期数据并使用新的日期数据选择它。
您生成 5 个日期的函数:-
CREATE FUNCTION [dbo].[tvfCustomDateRange] (@Increment char(1), @StartDate date, @EndDate date)
RETURNS @SelectedRange TABLE (cDate date)
AS
BEGIN
;WITH cteRange (DateRange) AS (
SELECT @StartDate
UNION ALL
SELECT
CASE
WHEN @Increment = 'd' THEN DATEADD(dd, 1, DateRange)
WHEN @Increment = 'w' THEN DATEADD(ww, 1, DateRange)
WHEN @Increment = 'm' THEN DATEADD(mm, 1, DateRange)
END
FROM cteRange
WHERE DateRange <=
CASE
WHEN @Increment = 'd' THEN DATEADD(dd, -1, @EndDate)
WHEN @Increment = 'w' THEN DATEADD(ww, -1, @EndDate)
WHEN @Increment = 'm' THEN DATEADD(mm, -1, @EndDate)
END)
INSERT INTO @SelectedRange (cDate)
SELECT DateRange
FROM cteRange
OPTION (MAXRECURSION 3660);
RETURN
END
CREATE FUNCTION [dbo].[tvfGenerate5Row] (@BeginDate DateTimeOffset, @EndDate Datetimeoffset)
RETURNS TABLE
AS
RETURN
(
SELECT tblCustom.Name,tblCustom.cDate, tblCustom.ID, 0 AS CHECKBOX
FROM (SELECT cDate, Name, ID
FROM tvfCustomDateRange('d', @BeginDate, @EndDate) CROSS JOIN tableWith5Row) AS tblCustom
)
并得到你的输出结果:
; WITH CTE AS (
select ID, MAX(CDATE) AS CDATE from dbo.tvfGenerate5Row( '2019-08-13', '2019-08-15' ) GROUP BY ID
)
SELECT CTE.ID, CTE.CDATE , CASE WHEN D.QUANTITY=1 THEN 1 ELSE 0 END AS CC FROM CTE
CROSS APPLY (
SELECT ID, MAX(QUANTITY) AS QUANTITY
FROM tblProduce AS TP
WHERE CTE.ID=TP.Idtbl5Row
AND QUANTITY = 1
) AS D
对于您在评论中提到的情况,认为您已经有回溯的条目。因此,您获得预期结果所需的查询将是:
; WITH CTE AS (
select ID, MAX(CDATE) AS CDATE from dbo.tvfGenerate5Row( '2019-08-13', '2019-08-15' ) GROUP BY ID )
, CT AS (
SELECT CTE.ID, CTE.CDATE , CASE WHEN D.QUANTITY=1 THEN 1 ELSE 0 END AS CC FROM CTE
CROSS APPLY (SELECT ID, MAX(QUANTITY) AS QUANTITY FROM tblProduce AS TP WHERE CTE.ID=TP.Idtbl5Row and QUANTITY=1 ) AS D
)
SELECT CT.ID,
CASE WHEN tblProduce.CHECKBOX = 1 THEN tblProduce.CDATE ELSE CT.CDATE END AS CDATE,
CASE WHEN tblProduce.CHECKBOX = 1 THEN tblProduce.QUANTITY ELSE 1 END AS QUANTITY
FROM CT LEFT JOIN ( SELECT * FROM tblProduce WHERE CHECKBOX=1 ) tblProduce ON CT.ID=tblProduce.Idtbl5Row
【讨论】:
感谢您的帮助,但我只想在复选框为 True 时获取以前的数据,如果复选框为 False,它应该生成新行。所以当我将第一行更改为 True 时,下一个数据应该生成 4 Row + 1 Previous Row Data。当我将第一行和第三行更改为 true 时,下一个数据应该生成 3 行 + 2 个上一行数据取决于 PrimaryKey 和 Name 谢谢你的回答,我试试这个 哦,对不起,你的答案绝对有效,但我还没有在我的真实桌子上尝试过,但我认为你的答案会在我的真实桌子上有效,我会试试这个晚上的真实代码,现在是下午 5 点,谢谢顺便说一句......真的对我有很大帮助(我在我的真实代码上测试后检查解决按钮) 而且我还需要更改您的答案并将其放入我的 [dbo].[tvfGenerate5Row] 代码中,因为 [dbo].[tvfGenerate5Row] 是我在 VB 上调用的那个行以上是关于如何在 SQL SERVER 2017 SSMS 中用以前保存的行值替换行值的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SQL Server 2014 中从 SQL Server 2008 R2 恢复备份?