Получить последнюю запись таблицы в Postgres - PullRequest
32 голосов
/ 07 июня 2011

Я использую Postgres и не могу получить последнюю запись моей таблицы:

 my_query = client.query("SELECT timestamp,value,card from my_table");

Как я могу это сделать, зная, что отметка времени является уникальным идентификатором записи?

Ответы [ 9 ]

67 голосов
/ 07 июня 2011

Если под «последняя запись» имеется в виду запись с последним значением метки времени, попробуйте следующее:

my_query = client.query("
  SELECT TIMESTAMP,
    value,
    card
  FROM my_table
  ORDER BY TIMESTAMP DESC
  LIMIT 1
");
14 голосов
/ 07 июня 2011

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

SELECT timestamp, value, card 
FROM my_table 
ORDER BY timestamp DESC 
LIMIT 1

при условии, что вы также хотите отсортировать по timestamp?

7 голосов
/ 13 апреля 2012

Если вы принимаете чаевые, создайте идентификатор в этой таблице, как серийный номер. Значение по умолчанию для этого поля будет:

nextval('table_name_field_seq'::regclass).

Итак, вы используете запрос для вызова последнего регистра. Используя ваш пример:

pg_query($connection, "SELECT currval('table_name_field_seq') AS id;

Надеюсь, этот совет поможет вам.

5 голосов
/ 21 ноября 2016

Последняя вставленная запись может быть запрошена, используя это при условии, что у вас есть «id» в качестве первичного ключа:

SELECT timestamp,value,card FROM my_table WHERE id=(select max(id) from my_table)

При условии, что каждая новая вставленная строка будет использовать самое высокое целочисленное значение для идентификатора таблицы.

3 голосов
/ 04 июля 2018

Простой способ: ORDER BY в сочетании с LIMIT

SELECT timestamp, value, card
FROM my_table
ORDER BY timestamp DESC
LIMIT 1;

Однако LIMIT не является стандартным и, как указано в Wikipedia , Основные функции стандарта SQL не указаны явноопределить порядок сортировки по умолчанию для пустых значений. .Наконец, только одна строка возвращается, когда несколько записей имеют максимальную временную метку.

Реляционный путь:

Типичный способ сделать это - проверить, что ни одна строка не имеет более высокой временной метки, чем любая строка, которую мыretrieve.

SELECT timestamp, value, card
FROM my_table t1
WHERE NOT EXISTS (
  SELECT *
  FROM my_table t2
  WHERE t2.timestamp > t1.timestamp
);

Это мое любимое решение, которое я использую.Недостатком является то, что наше намерение не сразу ясно, когда мы можем взглянуть на этот запрос.

Поучительный путь: MAX

Чтобы обойти это, можно использовать MAX в подзапросе вместо корреляции.

SELECT timestamp, value, card
FROM my_table
WHERE timestamp = (
  SELECT MAX(timestamp)
  FROM my_table
);

Но без индекса потребуется два прохода данных, тогда как предыдущий запрос может найти решение только с одним сканированием.Тем не менее, мы не должны принимать во внимание производительность при разработке запросов без необходимости, поскольку мы можем ожидать, что оптимизаторы со временем улучшатся.Однако этот конкретный тип запросов довольно часто используется.

Поговорим о: оконные функции

Я не рекомендую делать это, но, возможно, вы можете произвести хорошее впечатление на своего босса или что-то еще;-)

SELECT DISTINCT
  first_value(timestamp) OVER w,
  first_value(value) OVER w,
  first_value(card) OVER w
FROM my_table
WINDOW w AS (ORDER BY timestamp DESC);

На самом деле это имеет то преимущество, что показывает, что простой запрос может быть выражен различными способами (есть несколько других, которые я могу придумать), и что выбираем ту или иную формудолжно быть сделано в соответствии с несколькими критериями, такими как:

  • переносимость (реляционные / инструктивные способы)
  • эффективность (реляционные пути)
  • выразительность (простой / инструктивный способ)
0 голосов
/ 05 января 2019

Это все хорошие ответы, но если вы хотите, чтобы агрегатная функция делала это, чтобы захватить последнюю строку в наборе результатов, сгенерированном произвольным запросом, есть стандартный способ сделать это (взятый из Postgres wiki, но должен работать во всем, что в достаточной мере соответствует стандарту SQL десятилетия или более):

-- Create a function that always returns the last non-NULL item
CREATE OR REPLACE FUNCTION public.last_agg ( anyelement, anyelement )
RETURNS anyelement LANGUAGE SQL IMMUTABLE STRICT AS $$
        SELECT $2;
$$;

-- And then wrap an aggregate around it
CREATE AGGREGATE public.LAST (
        sfunc    = public.last_agg,
        basetype = anyelement,
        stype    = anyelement
);

Обычно предпочтительнее сделать select ... limit 1, если у вас разумный порядок, но это полезно, если вам нужно сделать это в совокупности и предпочитаете избегать подзапроса.

См. Также этот вопрос для случая, когда это естественный ответ.

0 голосов
/ 24 октября 2018

Если в вашей таблице нет идентификатора, такого как целочисленное автоинкремент, и нет отметки времени, вы все равно можете получить последнюю строку таблицы со следующим запросом.

select * from <tablename> offset ((select count(*) from <tablename>)-1)

Например, это может позволитьвыполнить поиск в обновленном плоском файле, найти / подтвердить, где закончилась предыдущая версия, и скопировать оставшиеся строки в таблицу.

0 голосов
/ 22 августа 2018

Чтобы получить последнюю строку,

Получить последнюю строку в отсортированном порядке : Если в таблице есть столбец с указанием времени / первичного ключа,

  1. Использование LIMIT предложения

SELECT * FROM USERS ORDER BY CREATED_TIME DESC LIMIT 1;

Использование предложения FETCH - Ссылка

SELECT * FROM USERS ORDER BY CREATED_TIME FETCH FIRST ROW ONLY;

Получить последнюю строку в порядке вставки строк : Весли в таблице нет столбцов с указанием времени / уникальных идентификаторов

Использование системного столбца CTID, где ctid представляет физическое местоположение строки в таблице - Ссылка

SELECT * FROM USERS WHERE CTID = (SELECT MAX(CTID) FROM USERS);

Рассмотрим следующую таблицу:

userid |username |    createdtime |
     1 |       A |  1535012279455 |
     2 |       B |  1535042279423 | //as per created time, this is the last row
     3 |       C |  1535012279443 |
     4 |       D |  1535012212311 |
     5 |       E |  1535012254634 | //as per insertion order, this is the last row

Запрос 1 и 2 возвращает,

userid |username |    createdtime |
     2 |       B |  1535042279423 |

, а 3 возвращает,

userid |username |    createdtime |
     5 |       E |  1535012254634 |

Примечание : При обновлении старой строки она удаляет старую строку, обновляет данные и вставляет в таблицу новую строку.Таким образом, использование следующего запроса возвращает кортеж, для которого выполняется изменение данных не позднее.

Теперь обновляем строку, используя

UPDATE USERS SET USERNAME = 'Z' WHERE USERID='3'

таблица становится,

userid |username |    createdtime |
     1 |       A |  1535012279455 |
     2 |       B |  1535042279423 |
     4 |       D |  1535012212311 |
     5 |       E |  1535012254634 |
     3 |       Z |  1535012279443 |

Теперь запрос 3 возвращает,

userid |username |    createdtime |
     3 |       Z |  1535012279443 |
0 голосов
/ 07 августа 2018

Используйте следующее

SELECT timestamp, value, card 
FROM my_table 
ORDER BY timestamp DESC 
LIMIT 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...