Sql 我有一个表,需要根据字段参数进行更新或插入

Sql 我有一个表,需要根据字段参数进行更新或插入,sql,sqlite,Sql,Sqlite,我花了很多时间研究这个问题,并尝试各种解决方案,但我从来没有找到一个适合我的具体问题的解决方案。我是SQL新手,其中一些示例也令人困惑 这就是我的困境。我有一个设备表,用于跟踪数据库中特定装置的换油情况。该表如下所示: **id UnitID Posted_On Date_Completed Note OverDueBy** 1 BT-109F 2019-02-04 2019-02-14 Hrs Overdue 23

我花了很多时间研究这个问题,并尝试各种解决方案,但我从来没有找到一个适合我的具体问题的解决方案。我是SQL新手,其中一些示例也令人困惑

这就是我的困境。我有一个设备表,用于跟踪数据库中特定装置的换油情况。该表如下所示:

     **id   UnitID   Posted_On    Date_Completed     Note     OverDueBy**
      1 BT-109F  2019-02-04   2019-02-14       Hrs  Overdue   23 
      1 BT-108G  2020-01-17   2020-01-22       Days Overdue   12
      1 BT-122K  2020-01-02   2020-01-16       Days Overdue   12
      1 BT-109F  2019-02-04                    Days Overdue   3 
MERGE INTO EQUIPMENT A 
USING (SELECT * FROM EQUIPMENT B WHERE DATE_COMPLETED IS NULL) C 
ON (A.UNITID=C.UNITID)
WHEN MATCHED THEN UPDATE SET  A.OVERDUEBY="new value"
WHEN NOT MATCHED THEN INSERT (A.id,A.UnitID,A.Posted_On,A.Date_Completed,A.Note,A.OverDueBy)
VALUES (C.id,C.UnitID,C.Posted_On,NULL,C.Note,C.OverDueBy)
上面的示例记录需要由查询创建或更新。完成日期由技师在完成机油更换后手动输入

我希望查询做的是,检查特定单元是否有“Date_Completed”字段为空的记录,如果是,则更新“OverDueBy”字段以反映新值。如果指定单位的所有记录都填写了“Date_Completed”(完成日期)字段,则查询应创建一个新记录,该记录将包含除“Date_Completed”(完成日期)字段之外的所有字段

有人能帮我构造这样一个查询吗

谢谢
Clan

首先,我会使用视图而不是表来存储任何计算数据-它减少了存储开销,并会在每次打开视图时更新计算。 如果您使用的是SQLite,您应该能够通过从其函数中减去Posted_On来返回今天的日期,例如
date('now')
julianday('now')
——阅读并测试函数,以确保它符合您的要求。 因此,大致如下:-

create view MyView as select *,  julianday('now') - julianday(Posted_On) as OverDueBy from ClansTable where Date_Completed is null; 
如果要存储快照,在任何情况下都可以从视图创建表:-

create table MyStoredOverduesOn4thFeb as select * from MyView;
您可以找到已完成所有日期的单位,并创建一个新记录,如下所示:-

Create table CompletedUnits as select id, UnitID, max(posted_on) as latest_posted_on, '' as Date_Completed from ClansTable group by id, UnitID having count(*) = count(Date_Complete); 
测试这个SQL,看看是否可以让它工作——注意,我已经为日期创建了一个文本字段。显然不存在这样的日期/日期时间数据类型:-

希望这有帮助


菲尔

我想你需要这样的东西:

     **id   UnitID   Posted_On    Date_Completed     Note     OverDueBy**
      1 BT-109F  2019-02-04   2019-02-14       Hrs  Overdue   23 
      1 BT-108G  2020-01-17   2020-01-22       Days Overdue   12
      1 BT-122K  2020-01-02   2020-01-16       Days Overdue   12
      1 BT-109F  2019-02-04                    Days Overdue   3 
MERGE INTO EQUIPMENT A 
USING (SELECT * FROM EQUIPMENT B WHERE DATE_COMPLETED IS NULL) C 
ON (A.UNITID=C.UNITID)
WHEN MATCHED THEN UPDATE SET  A.OVERDUEBY="new value"
WHEN NOT MATCHED THEN INSERT (A.id,A.UnitID,A.Posted_On,A.Date_Completed,A.Note,A.OverDueBy)
VALUES (C.id,C.UnitID,C.Posted_On,NULL,C.Note,C.OverDueBy)

不确定更新中的新值来自何处。你的问题不清楚。但是类似的方法可能会奏效。

首先为列
UnitID
创建一个唯一的部分索引:

CREATE UNIQUE INDEX idx_unit ON tablename(UnitID) 
WHERE Date_Completed IS NULL;
因此,对于每个
UnitID
,只允许有一行
Date\u Completed=null
这样的说法:

INSERT INTO tablename(id, UnitID, Posted_On, Date_Completed, Note, OverDueBy)
VALUES (?, 'BT-109F', ?, null, ?, ?)
ON CONFLICT(UnitID) WHERE Date_Completed IS NULL DO UPDATE
SET OverDueBy = ?;
仅当
UnitID='BT-109F'
Date\u Completed
中没有带
null的
行时,才会插入新值
但是如果有这样一行,它将更新列
OverDueBy


我不确定要插入什么值或更新的值是什么,因此请用适当的值替换

如果它确实是sqlite,我认为您不能,您需要的更像一个存储过程而不是查询,sqlite不支持存储过程。在您的位置上,我将编写3个单独的查询和一段python,根据您提到的逻辑运行它们如果您的
sqlite
版本支持所谓的UPSERT,那么这就是方法。我确信UPSERT可以与我的sqlite一起工作,并且我已经尝试使用示例格式化查询,但我没有足够的经验来正确处理它。有人吗?这不是upsert的目的。这是由主键或唯一索引冲突触发的。我感谢您的帮助,这将适用于按日期过期的字段,但单位也可能因小时计读数过期。查询将由节点红色函数每天运行一次。如果PMI(换油)未完成,则查询(我希望)将更新字段中的当前工时计读数。我想我可以对Unit和IsNull(“Date_completed”)执行“select”语句过滤,如果出现错误,则插入其他更新。(只是不知道怎么做)好的,那么改用datetime()函数怎么样?我确实在node red函数中使用了datetime函数,但查询是另一个故事SQLite不支持合并。谢谢。我明天试试这个。(下午剩下的时间都得出去)。我会让你知道这是怎么回事。:)我确实创建了索引,但第二部分不起作用。我得到以下消息:ON CONFLICT子句不匹配任何主键或唯一约束。不确定下一步要尝试什么。是否复制了带有“WHERE Date_Completed is NULL”的代码?语法正确。检查这个:我做了,但我会检查链接并返回给你。我们又得出去了,所以我最早要到明天早上才能给你回电话。(医院里的家人)@forpast非常感谢你。这很有效。我很惊讶你提出了这个解决方案。我不会想到使用唯一的索引。非常聪明。:)