Обновление с помощью Где, Order by и Limit не работает - PullRequest
0 голосов
/ 26 сентября 2018

Я использую SQLite 3.

При вводе следующего запроса

UPDATE MyTable Set Flag = 1 WHERE ID = 5 Order By OrderID DESC LIMIT 1;

я всегда получаю сообщение об ошибке:

возле Order By,синтаксическая ошибка

Я не могу понять, в чем проблема с моим запросом

Ответы [ 6 ]

0 голосов
/ 29 сентября 2018

Порядок по заявке не будет работать в запросе на обновление.Вы должны использовать альтернативный способ

UPDATE MyTable Set Flag = 1 WHERE ID = 5 
and OrderId = (select max(OrderId) from MyTable where Id = 5);

Если вы использовали запрос, как указано выше, он будет работать.

0 голосов
/ 28 сентября 2018

SQL

UPDATE MyTable
SET Flag = 1
WHERE ID = 5
AND OrderID IN (SELECT OrderID
                FROM MyTable
                WHERE ID = 5
                ORDER BY OrderID DESC
                LIMIT 1);

Демо

Демо SQLFiddle: http://sqlfiddle.com/#!5/6d596/2

0 голосов
/ 28 сентября 2018

Вы можете использовать ROWID:

UPDATE MyTable 
SET Flag = 1 
WHERE ROWID IN (SELECT ROWID FROM MyTable WHERE ID = 5 
                ORDER BY OrderID DESC LIMIT 1);

db <> fiddle demo

или (ID,OrderID) кортеж:

UPDATE  MyTable 
SET Flag = 1 
WHERE (ID, ORDERID) IN (SELECT  ID, ORDERID FROM MyTable WHERE ID = 5 
                        ORDER BY OrderID DESC LIMIT 1);

db <> fiddle demo2


И если вам нужно сделать это навалом для каждого идентификатора (SQLite 3.25.0):

WITH cte AS (
  SELECT *,ROW_NUMBER() OVER(PARTITION BY ID ORDER BY OrderID DESC) AS rn FROM tab
)
UPDATE tab
SET Flag = 1
WHERE (ID, OrderID) IN (
       SELECT ID, OrderID
       FROM cte
       WHERE rn = 1
      );
0 голосов
/ 28 сентября 2018

Введение

Ниже я представляю два решения для решения проблемы и выполнения правильного UPDATE.В конце каждого решения приведен живой пример с примерами данных.

  • Первый не требует ввода id и работает для всей таблицывыбрав последний orderid для каждого id и изменив его flag на 1

  • Секунда , требуется ввести id иработает только для обновления одного id при запуске

Я бы лично выбрал решение first , но я не уверен насчет вашего требования, поэтому выложил двавозможности.

Первое решение - обновить всю таблицу

Объяснение здесь, для прокрутки кода вниз.

Для этого мы будем использовать Значение строки конструкция (id, orderid) точно так же, как для второго решения.Он найдет последнюю строку на основе orderid и обновит только эту строку для данной пары (id, orderid).Более подробная информация об этом включена в Объяснение второго решения.

Нам также нужно будет смоделировать функцию row_number, чтобы назначать номера ранжирования каждой строке, чтобы выяснить, какая строка имеет самую последнюю orderid для каждой idи пометьте тогда как 1, чтобы иметь возможность получать только те, которые обновляются.Это позволит нам обновить несколько строк для разных идентификаторов в одном операторе.SQLite будет иметь эту функциональность , встроенную в версию 3.2.5 , но сейчас мы будем работать с подзапросом.

Для генерации номеров строк мы будем использовать это:

select 
  *, 
  (select count(*) from mytable m1 where m1.id = m2.id and m1.orderid >= m2.orderid) as rn
from mytable m2

Тогда нам просто нужно отфильтровать вывод по rn = 1, и у нас есть то, что нам нужно.

Тем не менее, весь оператор UPDATE будет выглядеть так:

Код

update mytable
set flag = 1
where (id,orderid) in (
  select id, orderid
  from (
    select *, (select count(*) from mytable m1 where m1.id = m2.id and m1.orderid >= m2.orderid) as rn
    from mytable m2
    ) m
  where 
    m.rn = 1
    and m.id = mytable.id
  );

Live DEMO

Вот db fiddle , чтобы увидеть это решение вживую на данных выборки.


Второе решение - обновить только один идентификатор

Если вы знаете, что ваш ID должен быть обновлен, и хотите выполнить оператор UPDATE только для одного идентификатора, то это будет работать:

Код

update mytable
set flag = 1
where (id,orderid) in (
  select id, orderid
  from mytable
  where id = 5
  order by orderid desc
  limit 1
  );

Пояснение

(id, orderid) - это конструкция, называемая Значение строки, для которого SQLite сравнивает скалярные значения слева направо.

Пример взят из документации:

SELECT (1,2,3) = (1,2,3) -- outputs: 1

Live DEMO

Вот дБfiddle , чтобы увидеть это решение вживую на данных выборки.

0 голосов
/ 26 сентября 2018

Чтобы использовать LIMIT и ORDER BY в выражении UPDATE или DELETE, вы должны сделать две вещи:

  • Создать собственную версию объединения sqlite3.c из исходного кода, сконфигурировав ее с помощью *Опция 1004 *.
  • Скомпилируйте этот собственный sqlite3.c в свой проект с SQLITE_ENABLE_UPDATE_DELETE_LIMIT , определенным как 1.
0 голосов
/ 26 сентября 2018

"Order By OrderID DESC LIMIT 1" - для выбора одного из лучших упорядоченных результатов, поэтому вы должны использовать его в запросе выбора.Вы должны выполнить подзапрос, в котором сначала получите идентификатор, а затем обновите его:

UPDATE  MyTable 
SET Flag = 1 
WHERE (ID,OrderID) IN (SELECT ID,OrderID
FROM MyTable 
WHERE ID = 5 
ORDER BY OrderID DESC LIMIT 1);

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...