使用其他行的数据更新同一表中的行 SQL

Posted

技术标签:

【中文标题】使用其他行的数据更新同一表中的行 SQL【英文标题】:Update row SQL in same table with data from other row 【发布时间】:2021-04-14 12:33:53 【问题描述】:

我坚持使用 SQL 查询来更新同一个表中的不同行。但是 1 行必须从具有相同参考 ID (bst__ref) 的另一行获取数据。

当前表bstlyn__

A B C D E F G
157035 1/01/1980 2/04/2021 117210 N 0 N
157035 1/01/1980 25/03/2021 128078 N 0 N
157035 1/01/1980 25/03/2021 128078 N 0 N
157036 1/01/1980 12/04/2021 117022 N 0 N
157036 1/01/1980 12/04/2021 117034 N 0 N
157036 1/01/1980 9/04/2021 128078 N 0 N

当前 SQL 查询

UPDATE bstlyn__ SET G = 'Y', F = 'N', B = C WHERE E = 'N' AND F = '0'

这会导致将所有vrz__dat 行更改为与vrzv_dat 中相同的值。但正如您在同一个bst__ref 中看到的,所有afg__ref 的值为128078 的vrzv_dat 具有不同的vrzv_dat。这应该与bst__ref 中没有afg__ref 128078 的(第一)行相同的日期/vrz__dat

所以,运行上面的查询后,我得到:

bst__ref (A) vrz__dat (B) vrzv_dat (C) afg__ref (D) fiat____ (E) fac__tst (F) vrz__tst (G)
157035 2/04/2021 2/04/2021 117210 N N Y
157035 25/03/2021 25/03/2021 128078 N N Y
157035 25/03/2021 25/03/2021 128078 N N Y
157036 12/04/2021 12/04/2021 117022 N N Y
157036 12/04/2021 12/04/2021 117034 N N Y
157036 9/04/2021 9/04/2021 128078 N N Y

但应该是:

bst__ref vrz__dat vrzv_dat afg__ref fiat____ fac__tst vrz__tst
157035 2/04/2021 2/04/2021 117210 N N Y
157035 2/04/2021 25/03/2021 128078 N N Y
157035 2/04/2021 25/03/2021 128078 N N Y
157036 12/04/2021 12/04/2021 117022 N N Y
157036 12/04/2021 12/04/2021 117034 N N Y
157036 12/04/2021 9/04/2021 128078 N N Y

我到底如何只使用 SQL 来做到这一点? 谢谢!

【问题讨论】:

您使用的是哪个 dbms? FireDAC / Phys / ODBC / Microsoft / SQL Server Native Client 11.0 什么定义了“第一行” 你如何订购它们? @Charlieface no Idea tbh,但通常第一行永远不会出现在afg__ref 128078 如果您无法定义我们如何获得第一行,我们该如何解决?请记住,表没有固有的顺序,每次返回的结果都可能不同,而没有明确的顺序 【参考方案1】:

您需要关联回同一张表。有多种方法可以做到这一点,您似乎想专门针对单个值执行此操作,所以如果我理解正确,您可以尝试一下

update b set 
vrz__tst = 'Y',
fac__tst = 'N',
vrz__dat = 
    case when afg_ref=128078 then 
        (select Min(vrzv_dat) from bstlyn__ b2 where b2.bst_ref=b.bst_ref)
    else vrzv_dat end
from  bstlyn__ b
where fiat____ = 'N' and fac__tst = '0'

【讨论】:

嗯,如果您的意思是Min(vrzv_dat),那么它的输出与使用我的查询相同。如果您的意思是Min(vrz__dat),那么它不会更改任何具有afg__ref128078 的行。它应该将这些也从没有afg__ref 128078 的1 行更改为相同的vrzv_dat(但共享相同的bst__ref)。很难解释,不是吗... :-) 是的,也许我的意思是——我见过更容易阅读的查询。如果会更好,对于示例数据示例,您只需命名列 A、B、C 等:) 更改了上表中的列名,希望现在更容易理解。所以; B 必须成为与 C 相同的值,但是当 D 具有值“128078”时,它必须搜索 A 的相同行,然后从第一行(或 D 中没有“128078”的行中选择日期) 来自 C 列并更新它。因此,来自同一列 A 的所有行都需要在列 C 中具有相同的值 啊哈!我想我找到了; update b set vrz__tst = 'Y', fac__tst = 'N', vrz__dat = case when afg__ref='128078' then (select Max(vrzv_dat) from bstlyn__ b2 where b2.bst__ref=b.bst__ref) else vrzv_dat end from bstlyn__ b where fiat____ = 'N' and fac__tst = '0' 当然,在这种情况下,日期总是必须更高,但在我的用例中(通常)总是这样。【参考方案2】:

你可以使用这个表两次,你只需要在子查询中给表起别名。然后对每个相同的 A 代码只执行第一个检索

试试这个代码:

UPDATE bstlyn__ t, (SELECT DISTINCT A,B,C,D,E,F,G
                    FROM bstlyn__ ) t1
SET t.B = t1.C, G = 'Y', F = 'N'
WHERE t.A= t1.A

【讨论】:

我试过 UPDATE bstlyn__ SET vrz__tst = 'Y', fac__tst = 'N', vrz__dat = (SELECT vrzv_dat FROM (SELECT TOP 1 vrzv_dat FROM bstlyn__ ORDER BY bst__ref) t) WHERE fiat____ = 'N' AND fac__tst = '0' 但是它需要表格的第一个(日期为 4/05/2012) 对您的答案如何工作的一些解释将极大地批准这个答案。 OP 应该能够从中学习,而不仅仅是复制/过去并很高兴它有效。

以上是关于使用其他行的数据更新同一表中的行 SQL的主要内容,如果未能解决你的问题,请参考以下文章

基于其他表中的行的 PLSQL 更新

SQL:插入更新主键相同的行的所有其他列

在 DataGridView 中显示数据表 SQL RealTime

SQL递归逻辑

MySQL ------ 更新数据(UPDATE)(二十一)

MySQL ------ 更新数据(UPDATE)(二十一)