SQL: обновить строку, если * условие * в другой строке - PullRequest
3 голосов
/ 20 апреля 2020

У меня проблема в 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. обновление user на строка 1 , если allow на строка 2 меньше ?
  2. обновление allow на строка 2 (если allow на строка 2 меньше ?)

Условие для второй точки на самом деле не имеет значения, потому что оно обновил бы я Сам, но это единственный способ, которым я смог это сделать.

Моя проблема:

  • Первый фрагмент кода (не MySQL) обновляет upvotes on строка 1 но никогда не изменяется allow на строка 2 .
  • Обновляется второй фрагмент кода (MySQL) arrow на строка 2 но никогда не меняется user на строка 1 .

Есть ли у вас какие-либо решения, которые могут подразумевать уникальную версию MySQL + non- 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:

  • ничего не происходит.

параметры: «admin», 2, «2020-04-22», 2, «2020-04-22» allow на строка B ниже 2020-04-20:

  • upvotes на строка A в увеличенном (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 на увеличена строка C (1 -> 2)
  • allow на обновлена ​​строка A (2020-04-18 -> 2020-04-19)


ОБНОВЛЕНИЕ 2:

Что я хочу сделать: Если пользователь 1 хочет поднять пользователь 2 (каждый может поднять голос другого человека не чаще одного раза в день), когда он нажимает кнопку, allowed (в его ряду) сравнивается с днем ​​после :

  • если allowed равно на следующий день после , это означает, что пользователь 1 уже проголосовал против кого-либо (он может быть пользователь 2 , пользователь 3 или кто-то еще), поэтому ничего не меняется
  • , если allowed ниже, чем на следующий день после , это означает, что пользователь 1 может upvote кто-то, так что upvote для пользователя 2 увеличивается строка и allow для пользователя 1 строка обновляется до на следующий день после
* 1 176 * Не беспокойтесь о том, «что если пользователь 1 или пользователь 2 на самом деле не существует?», Или «что если пользователь 1 попытается поднять голос сам? * потому что я проверяю это в своем PHP коде.

Ответы [ 2 ]

1 голос
/ 29 апреля 2020

Я попытался найти решение для вашей проблемы, и у меня, возможно, есть идентификатор ответа, который я правильно понимаю, здесь поток работ: каждый пользователь может поднять голос 1 раз в день

  1. user1 upvote user2
  2. имеет ли user1 уже upvote сегодня?
    -> yes: ничего не делать
    -> no: изменить дату user1 и +1 на upvotes пользователя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.

1 голос
/ 25 апреля 2020

Давайте пройдемся по вещам. Во-первых, давайте уточним каждый столбец, чтобы понять, какой столбец находится в какой таблице:

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

Теперь давайте 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 < ?;
...