简体   繁体   English

SQL:如果 *condition* 在另一行上,则更新一行

[英]SQL: update a row if *condition* on another row

I have a problem in SQL .我在SQL有问题。

I want to update a value on a given row if and only if a value on another row matches a condition;当且仅当另一行上的值与条件匹配时,我想更新给定行上的值; then update another value on the second row.然后更新第二行的另一个值。

Ok it can't be clear if I explain it in this way, so here's the code (I'm gonna bind the parameters using mysqli):好吧,如果我这样解释就不清楚了,所以这里是代码(我将使用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)

I have to keep both MySQL and non-MySQL versions because I have different databases on localhost and my host, and for some reason the first version does not work with MySQL.我必须保留 MySQL 和非 MySQL 版本,因为我在 localhost 和我的主机上有不同的数据库,并且由于某种原因,第一个版本不适用于 MySQL。

data is another table which has a one-to-one relationship with accountlist (they always have the same number of rows with the same id s) data是另一个与accountlist具有一对一关系的表(它们总是具有相同的行数和相同的id

Anyway, I'm gonna call the row where user=?无论如何,我将调用user=? row 1 and the row where accountlist.id=?第 1行和accountlist.id=?所在的行row 2 to simplify everything.第 2 行以简化一切。

What I want do do is:我想做的是:

  1. update user on row 1 if allow on row 2 is less than ?如果第 2行的allow值小于,则更新第 1 行user ?
  2. update allow on row 2 (if allow on row 2 is less than ? )更新第 2 行allow (如果第 2 行allow小于?

The condition on the second point doesn't really matter because it would update to itself, but that's the only way I was able to do that.第二点的条件并不重要,因为它会自我更新,但这是我能够做到这一点的唯一方法。

My problem:我的问题:

  • The first piece of code (non-MySQL) updates upvotes on row 1 but never changes allow on row 2 .第一段代码(非 MySQL)更新第 1 行upvotes ,但allow第 2 行的更改。
  • The second piece of code (MySQL) updates arrow on row 2 but never changes user on row 1 .第二段代码(MySQL)更新第 2 行arrow ,但从不更改第 1 行user

Do you have any solutions, which could maybe imply an unique MySQL + non-MySQL version?您是否有任何解决方案,这可能意味着独特的 MySQL + 非 MySQL 版本?



UPDATE:更新:

Here an example:这里有一个例子:

     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 on row B is not lower than 2020-04-20 : params: "admin", 2, "2020-04-20", 2, "2020-04-20" allow B 行低于2020-04-20

  • nothing happens.什么都没发生。

params: "admin", 2, "2020-04-22", 2, "2020-04-22" allow on row B is lower than 2020-04-20 : params: "admin", 2, "2020-04-22", 2, "2020-04-22" allow B 行低于2020-04-20

  • upvotes on row A in increased ( 2 -> 3 )A 行的upvotes增加( 2 -> 3
  • allow on row B is updated ( 2020-04-20 -> 2020-04-22 ) allow B 行已更新( 2020-04-20 -> 2020-04-22

params: "bar", 1, "2020-04-19", 1, "2020-04-19" allow on row A is lower than 2020-04-19 : params: "bar", 1, "2020-04-19", 1, "2020-04-19" allow A 行低于2020-04-19

  • upvotes on row C is increased ( 1 -> 2 ) upvotes的投票增加( 1 -> 2
  • allow on row A is updated ( 2020-04-18 -> 2020-04-19 ) allow A 行已更新( 2020-04-18 -> 2020-04-19


UPDATE 2:更新 2:

What I want to do: If user 1 wants to upvote user 2 (everyone can upvote someone else at most once a day), when it clicks a button, allowed (on his row) is compared with the day after :我想做的事情:如果用户 1想要投票给用户 2 (每个人每天最多可以投票一次),当它点击一个按钮时, allowed (在他的行上)与后一天进行比较:

  • if allowed is equal to the day after , it means that user 1 has already upvoted someone (he could be user 2 , user 3 or someone else), so nothing changes如果allowed等于day after ,则表示用户 1已经为某人投票(他可能是用户 2用户 3或其他人),所以没有任何变化
  • if allowed is lower than the day after , it means that user 1 is allowed to upvote someone, so upvote on user 2 's row is incremented and allow on user 1 's row is updated to the day after如果allowed低于day after ,则表示允许用户 1对某人进行投票,因此对user 2的行的upvote会递增,而在user 1的行上的allow会更新到后天

Don't worry about "what if user 1 or user 2 doesn't actually exist?", or "what if user 1 tries to upvote himself?* because I check about it in my PHP code.不要担心“如果用户 1用户 2实际上不存在怎么办?”,或者“如果用户 1试图给自己投票怎么办?*因为我在我的PHP代码中检查了它。

Let's walk through things.让我们来看看事情。 First, let be qualify each column to help see which column is in which table:首先,让每列限定以帮助查看哪一列在哪个表中:

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` < ?;

Oh, the two tables are 1:1 on id .哦,这两张桌子在id上是 1:1 的。 So let's pretend they are the same table.所以让我们假设它们是同一张桌子。 (And you should probably do that. 1:1 is usually not a good schema design.) (你可能应该这样做。1:1 通常不是一个好的模式设计。)

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

Now it is obvious that the CASE is wasted.现在很明显, CASE被浪费了。 So the query simplifies to所以查询简化为

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

Now let's go back to having 2 tables:现在让我们 go 回到有 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 < ?;

Which leads to another form.这导致了另一种形式。 (I don't know if this is better or not.) (我不知道这是否更好。)

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

Or, (again possibly not any significant difference):或者,(同样可能没有任何显着差异):

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 < ?;

I have tried to find a solution for your problem and I have possibly an answer id i understand correctly here the wor flow: each user can upvote 1 time per day我试图为您的问题找到解决方案,我可能有一个答案,我在这里正确理解工作流程:每个用户每天可以投票 1 次

  1. user1 upvote user2用户1点赞用户2
  2. have user1 already upvote today? user1 今天已经投票了吗?
    ->yes: do nothing -> 是:什么都不做
    ->no: change date of user1 and +1 to upvotes of user2 -> 否:将用户 1 的日期和 +1 更改为用户 2 的投票

in that exemple: "admin", 2, "2020-04-20", 2, "2020-04-20"在该示例中:“管理员”、2、“2020-04-20”、2、“2020-04-20”

  • 2 => user1 2 => 用户1
  • admin => user2管理员 => 用户 2
  • "2020-04-20" => date of upvote “2020-04-20” => 投票日期

Am I correct?我对么? if yes here my solution如果是的话,我的解决方案

mariadb 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 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;

created database:创建的数据库:

         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        |
   |------------|---------------|    |------------|--------------|----------|

with value: "admin", "2", "2020-04-20", "2", "2020-04-20" => no modification具有值:“admin”、“2”、“2020-04-20”、“2”、“2020-04-20” => 无修改

"admin", "2", "2020-04-22", "2", "2020-04-22" “管理员”、“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" => "酒吧", 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        |
   |------------|---------------|    |------------|--------------|----------|

normally that run correctly (tested online) but that coul have been simplier to use 2 statement instead of 1.通常可以正确运行(在线测试),但使用 2 语句而不是 1 语句更简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM