如果表中不存在当前记录,如何获取先前的记录

时间:2019-04-28 11:03:09

标签: sql-server

我的桌子是这样

    Id  Date    type    quantity
1   29/04/2019  APPLE   2
2   29/04/2019  Banana  15
3   29/04/2019  Mango   100
4   29/04/2019  Grapes  50
5   29/04/2019  Fish    80
6   30/04/2019  APPLE   4
7   30/04/2019  Grapes  100
8   30/04/2019  Fish    90
9   01/05/2019  APPLE   6
10  01/05/2019  Banana  30
11  01/05/2019  Grapes  150
12  01/05/2019  Fish    100
13  02/05/2019  Mango   200
14  02/05/2019  Grapes  200
15  02/05/2019  Fish    110
16  03/05/2019  APPLE   8
17  03/05/2019  Banana  45
18  03/05/2019  Mango   300
19  04/05/2019  APPLE   10
20  04/05/2019  Grapes  300
21  04/05/2019  Fish    120
22  05/05/2019  APPLE   12
23  05/05/2019  Fish    130

我每天都想念一些输入,但是我需要在2019/04/30填补与同一行“ Type”上一行的空白,我想念我想要的“ Banana&Mango”

    Id  Date    type    quantity
1   29/04/2019  APPLE   2
2   29/04/2019  Banana  15
3   29/04/2019  Mango   100
4   29/04/2019  Grapes  50
5   29/04/2019  Fish    80
6   30/04/2019  APPLE   4
7   30/04/2019  Grapes  100
8   30/04/2019  Fish    90
9   30/04/2019  Banana  15
10  30/04/2019  Mango   100

实际上最后两行为空,但应该在2019年4月29日更新

4 个答案:

答案 0 :(得分:4)

我认为简单的方法可能是这样:

DECLARE @PDate DATE = SELECT TOP 1 Date FROM YourTable ORDER BY Date ASC  --Previous Date
DECLARE @NDate DATE = SELECT TOP 1 Date FROM YourTable WHERE DATE>@PDate  --Next Date

WHILE (@NDate IS NOT NULL)
BEGIN

WITH X AS
(
 SELECT T1.Date AS Date1, T1.Type AS Type1, T1.Quantity AS Q1
        T2.Date AS Date2, T2.Type AS Type2, T2.Quantity AS Q2
 FROM YourTable T1
 LEFT JOIN YourTable T2 ON T1.Type = T2.Type
 WHERE T1.Date = @PDate AND T2.Date = @NDate
)
INSERT INTO YourTable (Date,Type,Quantity)
SELECT @NDate,Type1,Q1
WHERE X.Type2 IS NULL

SET @PDate = @NDate
SET @NDate = NULL  -- If next result wasnt found this stays null for while condition
SET @NDate = SELECT TOP 1 Date FROM YourTable WHERE Date>@PDate

END

我认为这是可行的方式,我希望如此
(如果有任何语法或...错误,是因为我没有安装SSMS进行测试。抱歉)

答案 1 :(得分:1)

尝试:

declare @date date

,对于启动@date,您可以使用select @date=max(date) from table1或传递静态值set @date='02/01/2019' 然后找到input

select input,max(date) as MaxDate into #temp 
from table1 
where input not in (select input from table1 where date=@date  ) 
group by input

然后:

select t.* from Table1 t join #temp on  Table1.input=#temp.Input and Table1.date=#temp.MaxDate

答案 2 :(得分:1)

我认为使用游标是在表中插入缺少的条目的好选择。通过光标,您将能够检查按日期排列的丢失类型,并使用先前的数量插入它们。

您还可以使用以下脚本在表中查找丢失的记录。为了创建脚本,我考虑表名称='add_missing_records'

SELECT AA.date AS [Date],
AA.type AS [Type],
BB.quantity AS [Original Quantity] ,
CASE 
    WHEN BB.quantity IS NULL THEN 
        ( 
            SELECT quantity 
            FROM add_missing_records C 
            WHERE C.date = (
                SELECT MAX([date]) 
                FROM add_missing_records B 
                WHERE B.date < AA.date 
                AND B.type = AA.type
            )
            AND C.type = AA.type
        ) 
    ELSE BB.quantity 
END AS [New Quantuty]

FROM (
    SELECT date,type
    FROM (
        SELECT DISTINCT 'A' AS common,date 
        FROM add_missing_records
    )A
    FULL JOIN (
        SELECT DISTINCT 'A' as common, type 
        FROM add_missing_records
    )B
    ON a.common = b.common
) AA
LEFT JOIN add_missing_records BB 
    ON AA.date = BB.date 
    AND AA.type = BB.type
WHERE BB.quantity IS NULL
ORDER BY 1,2

答案 3 :(得分:1)

好的,在结算目标职位之后,这是一种方法。请注意,此解决方案同时构建了TypesDates数据集。实际上,Types数据集应该已经存在于数据库中的某个地方 ,并且如果您要经常进行此类工作,则应该创建一个Calendar Table。

无论如何,我已经在代码中为您留下了注释。我假设,您正在使用SQL Server 2012+,因为从字面上看2008年将不再受支持。

CREATE TABLE dbo.MyTable (ID int IDENTITY(1,1),
                          [date] date,
                          [type] varchar(10),
                          Quantity int);
INSERT INTO dbo.MyTable
SELECT CONVERT(date,[date],103),
       RTRIM([Type]),
       Quantity
FROM (VALUES('29/04/2019','APPLE ',2),
            ('29/04/2019','Banana',15),
            ('29/04/2019','Mango ',100),
            ('29/04/2019','Grapes',50),
            ('29/04/2019','Fish  ',80),
            ('30/04/2019','APPLE ',4),
            ('30/04/2019','Grapes',100),
            ('30/04/2019','Fish  ',90),
            ('01/05/2019','APPLE ',6),
            ('01/05/2019','Banana',30),
            ('01/05/2019','Grapes',150),
            ('01/05/2019','Fish  ',100),
            ('02/05/2019','Mango ',200),
            ('02/05/2019','Grapes',200),
            ('02/05/2019','Fish  ',110),
            ('03/05/2019','APPLE ',8),
            ('03/05/2019','Banana',45),
            ('03/05/2019','Mango ',300),
            ('04/05/2019','APPLE ',10),
            ('04/05/2019','Grapes',300),
            ('04/05/2019','Fish  ',120),
            ('05/05/2019','APPLE ',12),
            ('05/05/2019','Fish  ',130)) V([date],[Type],Quantity);

GO
--SELECT *
--FROM dbo.MyTable;
GO
--Create a calendar table
WITH N AS (
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
    FROM N N1, N N2, N N3), --1000 days shuld be enough
Dates AS(
    SELECT DATEADD(DAY, T.I, MIN(MT.[date])) AS [Date]
    FROM Tally T
         CROSS JOIN dbo.MyTable MT
    GROUP BY T.I
    HAVING DATEADD(DAY, T.I, MIN(MT.[date])) <= MAX([Date])),
--Get Types
Types AS (
    SELECT DISTINCT [Type]
    FROM dbo.MyTable MT),
--Create islands
Grps AS(
    SELECT MT.ID,
           D.[Date],
           T.[Type],
           MT.Quantity,
           COUNT(MT.Quantity) OVER (PARTITION BY T.[Type] ORDER BY D.[date]
                                    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
    FROM Dates D
        CROSS JOIN Types T
        LEFT JOIN dbo.MyTable MT ON D.[Date] = MT.[date]
                                AND T.[type] = MT.[type])
SELECT G.ID AS ID,
       ROW_NUMBER() OVER (ORDER BY G.[Date], G.[Type]) AS RN,
       G.[Date],
       G.[Type],
       MAX(G.Quantity) OVER (PARTITION BY G.[Type], G.Grp) AS Quantity
FROM Grps G
ORDER BY G.[Date],
         G.[Type];

GO
DROP TABLE dbo.MyTable;

db<>fiddle