簡體   English   中英

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

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

我在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 版本,因為我在 localhost 和我的主機上有不同的數據庫,並且由於某種原因,第一個版本不適用於 MySQL。

data是另一個與accountlist具有一對一關系的表(它們總是具有相同的行數和相同的id

無論如何,我將調用user=? 第 1行和accountlist.id=?所在的行第 2 行以簡化一切。

我想做的是:

  1. 如果第 2行的allow值小於,則更新第 1 行user ?
  2. 更新第 2 行allow (如果第 2 行allow小於?

第二點的條件並不重要,因為它會自我更新,但這是我能夠做到這一點的唯一方法。

我的問題:

  • 第一段代碼(非 MySQL)更新第 1 行upvotes ,但allow第 2 行的更改。
  • 第二段代碼(MySQL)更新第 2 行arrow ,但從不更改第 1 行user

您是否有任何解決方案,這可能意味着獨特的 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" allow B 行低於2020-04-20

  • A 行的upvotes增加( 2 -> 3
  • allow B 行已更新( 2020-04-20 -> 2020-04-22

params: "bar", 1, "2020-04-19", 1, "2020-04-19" allow A 行低於2020-04-19

  • upvotes的投票增加( 1 -> 2
  • allow A 行已更新( 2020-04-18 -> 2020-04-19


更新 2:

我想做的事情:如果用戶 1想要投票給用戶 2 (每個人每天最多可以投票一次),當它點擊一個按鈕時, allowed (在他的行上)與后一天進行比較:

  • 如果allowed等於day after ,則表示用戶 1已經為某人投票(他可能是用戶 2用戶 3或其他人),所以沒有任何變化
  • 如果allowed低於day after ,則表示允許用戶 1對某人進行投票,因此對user 2的行的upvote會遞增,而在user 1的行上的allow會更新到后天

不要擔心“如果用戶 1用戶 2實際上不存在怎么辦?”,或者“如果用戶 1試圖給自己投票怎么辦?*因為我在我的PHP代碼中檢查了它。

讓我們來看看事情。 首先,讓每列限定以幫助查看哪一列在哪個表中:

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

哦,這兩張桌子在id上是 1:1 的。 所以讓我們假設它們是同一張桌子。 (你可能應該這樣做。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` < ?;

現在讓我們 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 < ?;

這導致了另一種形式。 (我不知道這是否更好。)

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點贊用戶2
  2. user1 今天已經投票了嗎?
    -> 是:什么都不做
    -> 否:將用戶 1 的日期和 +1 更改為用戶 2 的投票

在該示例中:“管理員”、2、“2020-04-20”、2、“2020-04-20”

  • 2 => 用戶1
  • 管理員 => 用戶 2
  • “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” => 無修改

“管理員”、“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        |
   |------------|---------------|    |------------|--------------|----------|

"酒吧", 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 語句更簡單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM