SQL:如果*条件*在另一行上,则更新一行。

问题描述 投票:2回答:1

我有一个问题,在 SQL.

我想更新某一行的值,如果且仅当另一行的值符合条件时;然后更新第二行的另一个值。

好吧,如果我这样解释就不清楚了,所以这是代码(我要用mysqli绑定参数)。

--mariaDB:

UPDATE `accountlist` JOIN `data` ON `accountlist`.`id`=`data`.`id`
    SET `upvotes`= `upvotes` + (`user`= ?),
        `allow` = (CASE WHEN `accountlist`.`id` = ?
                   THEN ?
                   ELSE `allow`
                   END)
WHERE (SELECT `allow` FROM `data` WHERE `id` = ?) < ?;

--mysql:

UPDATE `accountlist` JOIN `data` ON `accountlist`.`id`=`data`.`id`
    SET `upvotes`= `upvotes` + (`user`= ?),
        `allow` = (CASE WHEN `accountlist`.`id` = ?
                   THEN ?
                   ELSE `allow`
                   END)
WHERE `data`.`id` = ? AND `allow` < ?;

--params sample: "admin", 2, "2020-04-20", 2, "2020-04-20"
--               (same value here means always same value)

我必须同时保留MySQL和非MySQL版本 因为我在本地主机和主机上有不同的数据库 由于某些原因,第一个版本不能与MySQL一起使用。

data 是另一个表,它与之有一对一的关系。accountlist (它们总是有相同的行数,有相同的 ids)

总之,我要把这一排的地方叫做 user=? 第1行 和所在行 accountlist.id=? 第二行 以简化一切。

我想做的是:

  1. 更新 user 关于 第1行 如果 allow 关于 第二行 小于 ?
  2. 更新 allow 关于 第二行 (如果 allow 关于 第二行 小于 ?)

第二点的条件并不重要,因为它会更新到自己身上,但这是我能够做到的唯一方法。

我的问题是

  • 第一段代码(非MySQL)会更新... ... upvotes 关于 第1行 不变 allow 关于 第二行.
  • 第二段代码(MySQL)更新 arrow 关于 第二行 不变 user 关于 第1行.

你有什么解决方案,这也许意味着一个独特的MySQL +非MySQL版本?



更新。

这里有一个例子。

     accountlist                       data
   |------------|---------------|    |------------|--------------|----------|
   | id         | user          |    | id         | allow        | upvotes  |
   |------------|---------------|    |------------|--------------|----------|
A: | 1          | admin         |    | 1          | 2020-04-18   | 2        |
B: | 2          | foo           |    | 2          | 2020-04-20   | 0        |
C: | 3          | bar           |    | 3          | 2020-04-22   | 1        |
   |------------|---------------|    |------------|--------------|----------|

params: "admin", 2, "2020-04-20", 2, "2020-04-20"allow 关于 B行 低于 2020-04-20:

  • 什么都没有发生。

params. "admin",2,"2020-04-22",2,"2020-04-22"。"admin", 2, "2020-04-22", 2, "2020-04-22"allow 关于 B行 低于 2020-04-20:

  • upvotes 关于 一行 在增加(2->3)
  • allow 关于 B行 是更新的(2020-04-20->2020-04-22)

params. "bar",1,"2020-04-19",1,"2020-04-19"。"bar",1,"2020-04-19",1,"2020-04-19"allow 关于 一行 低于 2020-04-19:

  • upvotes 关于 丙行 是增加(1->2)
  • allow 关于 一行 是更新的(2020-04-18->2020-04-19)


更新2。

我想做的是:如果 用户1 想加注 用户2 每个人每天最多可以给别人加一次票),当它点击一个按钮。allowed后天:

  • 如果 allowed 等于 后天这意味着 用户1 已经给某人加了票(他可能是 用户2, 用户3 或别人),所以什么都没变
  • 如果 allowed 低于 后天这意味着 用户1 允许给某人加票,所以 upvote 关于 用户2的行被递增,并且 allow 关于 用户1的行更新为 后天

不要担心 "如果 用户1用户2 实际上并不存在?",或 "如果 用户1 因为我检查了一下我的。PHP 代码。

mysql sql mariadb case where-clause
1个回答
1
投票

让我们来演练一下。 首先,让我们对每一列进行限定,以帮助看清哪一列是在哪个表中。

UPDATE a JOIN d ON a.`id` = d.`id`
    SET d.`upvotes`= d.`upvotes` + (a.`user`= ?),
        d.`allow` = (CASE WHEN a.`id` = ?
                   THEN ?
                   ELSE d.`allow`
                   END)
WHERE d.`id` = ? AND d.`allow` < ?;

哦,这两张表是1: 1的,在... id. 所以让我们假设它们是同一个表。 1:1通常不是一个好的模式设计)。

UPDATE ad
    SET `upvotes`= `upvotes` + (`user`= ?),
        `allow` = (CASE WHEN `id` = ?
                   THEN ?
                   ELSE `allow`
                   END)
WHERE `id` = ? AND `allow` < ?;

现在很明显 CASE 是浪费的。 所以查询简化为

UPDATE ad
    SET `upvotes`= `upvotes` + (`user`= ?),
        `allow` = ?
WHERE `id` = ? AND `allow` < ?;

现在让我们回到有2张表。

UPDATE a JOIN d ON a.`id` = d.`id`
    SET d.upvotes = d.upvotes + (a.user = ?),
        d.allow = ?
    WHERE d.id = ? AND d.allow < ?;

这就导致了另一种形式: (我不知道这是否更好。)

UPDATE d
    SET d.upvotes = d.upvotes +
                    ( ( SELECT  user = ? FROM a WHERE a.id = d.id ) )
        d.allow = ?
    WHERE d.id = ? AND d.allow < ?;

或者,(同样可能没有任何显著区别)。

UPDATE d
    SET d.upvotes = d.upvotes +
                EXISTS ( SELECT  user = ? FROM a WHERE a.id = d.id )
        d.allow = ?
    WHERE d.id = ? AND d.allow < ?;

1
投票

我试着为你的问题找到一个解决方案 我有一个可能的答案 我正确地理解了这里的工作流程: 每个用户每天可以向上投票1次。

  1. 用户1向上投票 用户2
  2. 用户1今天是否已经加了票? ->yes : 不做任何事情 ->no : 更改用户1的日期,并将+1改成用户2的上票数

在该示例中:"admin",2,"2020-04-20",2,"2020-04-20"

  • 2 => user1
  • admin => user2
  • "2020-04-20" => 上票日期

我是正确的吗?如果是,我的解决方案在这里

mariadb

UPDATE data SET upvotes = CASE WHEN id = (SELECT id FROM accountlist WHERE accountlist.user = ?)
                AND 
               (SELECT allow FROM data inner join accountlist on accountlist.id = data.id 
                 where accountlist.id = ? )< ?
            THEN upvotes + 1
            ELSE upvotes
          END,
allow = CASE WHEN id = ?
THEN ?
ELSE allow
END

mysql

UPDATE data
SET upvotes = CASE WHEN id = (SELECT id FROM (select * from accountlist) as al WHERE al.user = "bar")
                    AND 
                   (SELECT allow FROM (select * from data) as d inner join (select * from accountlist) as al1 on al1.id = d.id where al1.id = 1)<"2020-04-19"
                THEN upvotes + 1
                ELSE upvotes
              END,
allow = CASE WHEN id = 1
THEN "2020-04-19"
ELSE allow
END;

创建数据库:

         accountlist                       data
   |------------|---------------|    |------------|--------------|----------|
   | id         | user          |    | id         | allow        | upvotes  |
   |------------|---------------|    |------------|--------------|----------|
A: | 1          | admin         |    | 1          | 2020-04-18   | 2        |
B: | 2          | foo           |    | 2          | 2020-04-20   | 0        |
C: | 3          | bar           |    | 3          | 2020-04-22   | 1        |
   |------------|---------------|    |------------|--------------|----------|

值:"admin","2","2020-04-20","2","2020-04-20"=> 没有修改。

"admin"、"2"、"2020-04-22"、"2"、"2020-04-22"

         accountlist                       data
   |------------|---------------|    |------------|--------------|----------|
   | id         | user          |    | id         | allow        | upvotes  |
   |------------|---------------|    |------------|--------------|----------|
A: | 1          | admin         |    | 1          | 2020-04-18   | 3        |
B: | 2          | foo           |    | 2          | 2020-04-22   | 0        |
C: | 3          | bar           |    | 3          | 2020-04-22   | 1        |
   |------------|---------------|    |------------|--------------|----------|

"bar", 1, "2020-04-19", 1, "2020-04-19" =>

             accountlist                       data
   |------------|---------------|    |------------|--------------|----------|
   | id         | user          |    | id         | allow        | upvotes  |
   |------------|---------------|    |------------|--------------|----------|
A: | 1          | admin         |    | 1          | 2020-04-19   | 3        |
B: | 2          | foo           |    | 2          | 2020-04-22   | 0        |
C: | 3          | bar           |    | 3          | 2020-04-22   | 2        |
   |------------|---------------|    |------------|--------------|----------|

通常情况下,运行正确(在线测试),但可以更简单地使用2个语句而不是1个。

© www.soinside.com 2019 - 2024. All rights reserved.