Изменение порядка сортировки MySQL между страницами 1 и 2 - PullRequest
0 голосов
/ 29 апреля 2019

У меня странная проблема, когда при попытке получить вторую страницу набора результатов, используя LIMIT 40 OFFSET 40, упорядочивается весь запрос иначе, что означает, что некоторые строки с первой страницы появляются снова, а некоторые строки никогда не показываются.

Я создал SQL Fiddle, используя копию моей схемы и данных, но он отлично работает здесь: http://www.sqlfiddle.com/#!9/5d8d3e/1 (полный пример также приведен внизу)

В этом примере первый запрос возвращает первую страницу, а второй запрос возвращает вторую страницу, и ни один из элементов на второй странице ранее не отображался на первой странице. Именно то, что вы ожидаете.

Однако, когда я запускаю эту одну и ту же вещь как в своей локальной среде (Vagrant VM с Ubuntu и MySQL), так и в моей производственной среде (экземпляр MySQL Azure), я получаю странные результаты.

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

Это не обязательно случай, когда «последний элемент» отличается, я просто специально сделал это так, чтобы появилась только одна строка с «owner_type_id» = 1, чтобы упростить проверку. Проблема в том, что если я использую смещение, порядок выглядит совершенно другим, что для меня абсолютно бессмысленно.

Я включил скриншот того, что вижу:

SELECT id, fm_id, name, owner_type FROM `stadiums_test` WHERE `capacity` > '70000' ORDER BY `owner_type` DESC LIMIT 40 OFFSET 0;

enter image description here

SELECT id, fm_id, name, owner_type FROM `stadiums_test` WHERE `capacity` > '70000' ORDER BY `owner_type` DESC LIMIT 40 OFFSET 0;

enter image description here

В основном при использовании LIMIT 40 OFFSET 0 стадион "Сантьяго Бернабеу" - единственный, показанный с "типом владельца", равным "1".

Но при использовании LIMIT 40 OFFSET 40, чтобы получить следующую "страницу". Сантьяго Бернабеу все еще показывают, а стадион «Олд Траффорд» никогда не показывают.

Вы можете увидеть полные результаты без limit или offset на этом скриншоте:

Стоит отметить, что порядок элементов с типом "owner_type", равным "1", также отличается при выборе всех результатов и при ограничении результатов.

SELECT id, fm_id, name, owner_type FROM `stadiums_test` WHERE `capacity` > '70000' ORDER BY `owner_type` DESC;

enter image description here

Я понимаю, что мог бы сделать что-то вроде вторичной сортировки по name или id, чтобы исправить это. Но я бы предпочел понять, почему это происходит, чем просто сделать быстрое решение.

Полная схема и данные

CREATE TABLE `stadiums_test` (
  `id` int(10) unsigned NOT NULL,
  `fm_id` bigint(20) unsigned DEFAULT NULL,
  `name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `owner_type` tinyint(3) unsigned DEFAULT NULL,
  `capacity` mediumint(8) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `fm_id` (`fm_id`)
) ENGINE=InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `stadiums_test` (`id`, `fm_id`, `NAME`, `owner_type`, `capacity`)
VALUES
    (6, 603, 'sfsfsfs', 1, 427773),
    (74, 680, 'Old Trafford', 1, 75635),
    (380, 1404, 'EverBank Field', 2, 76867),
    (459, 1040, 'Camp Nou', 1, 99354),
    (475, 1056, 'Santiago Bernabéu', 1, 81044),
    (609, 1205, 'Giuseppe Meazza', NULL, 80018),
    (632, 1229, 'San Paolo', NULL, 76824),
    (688, 1293, 'SIGNAL IDUNA PARK', 1, 81365),
    (707, 1317, 'Olympiastadion Berlin', 2, 74649),
    (744, 1357, 'Ohio Stadium', NULL, 102329),
    (746, 1359, 'The Cotton Bowl', 2, 92100),
    (747, 1360, 'Arrowhead Stadium', 2, 76416),
    (748, 1361, 'Rose Bowl', 2, 92542),
    (1105, 102531, 'Mineirão', 2, 75783),
    (1121, 102549, 'Morumbi', 1, 77011),
    (1132, 102569, 'Yokohama International Stadium', 2, 72327),
    (1186, 102969, 'Wembley', NULL, 90000),
    (1228, 102984, 'Millennium Stadium', NULL, 74500),
    (1229, 102987, 'Maracanã', 2, 78838),
    (1249, 103037, 'Cairo International Stadium', NULL, 74100),
    (1268, 103089, 'Surulere', NULL, 80000),
    (1280, 103142, 'Olympic Stadium', 2, 72000),
    (1281, 103143, 'Estadio Azteca', 1, 81070),
    (1317, 103241, 'Gelora Bung Karno', 2, 77193),
    (1318, 103242, 'Azadi', 2, 84412),
    (1324, 103248, 'May Day Stadium', 2, 114000),
    (1329, 103255, 'Shah Alam', 2, 80372),
    (1677, 120229, 'Stadium Australia', NULL, 80000),
    (1698, 127224, 'Raymond James Stadium', 2, 75000),
    (2105, 131243, 'FNB Stadium', NULL, 87600),
    (2144, 134929, 'Rajamangala National Stadium', 2, 80000),
    (2435, 152587, 'Stade des Martyrs', NULL, 80000),
    (2436, 156312, 'San Siro', NULL, 90018),
    (3060, 400123, 'Stade de France', NULL, 81338),
    (3133, 425196, 'Melbourne Cricket Ground', NULL, 97474),
    (5889, 978164, 'Sports Authority Field at Mile High', 2, 77160),
    (5953, 1003845, 'Naghsh-e Jahan', 1, 75000),
    (5954, 1003846, 'Yadegar-e Emam', 2, 71000),
    (6530, 1301278, 'NSC Olympiyskyi', NULL, 70050),
    (6735, 1301095, 'Luzhniki', 2, 81006),
    (8412, 5620132, 'Guangdong Olympic Sports Centre', 2, 80012),
    (8514, 5625181, 'Nasional Bukit Jalil', 2, 110000),
    (8662, 5627556, 'National Olympic Stadium \'Bird\'s Nest\'', 2, 80000),
    (9826, 7452614, 'Estadio Olímpico de Sevilla', NULL, 72000),
    (11676, 8476343, 'Atatürk Olimpiyat Stadyumu', 2, 76092),
    (12058, 8700726, 'Stadion München', 1, 75024),
    (12097, 8826792, 'Estadio Monumental', 1, 80000),
    (12724, 13201012, 'Grand Stade de Casablanca', 2, 80000),
    (13917, 16031791, 'Wiener Prater Stadion', NULL, 92708),
    (17075, 19141000, 'Estádio Nacional Mané Garrincha', 2, 72788),
    (17323, 20032542, 'Bank of America Stadium', 3, 74113),
    (17335, 20033734, 'Qualcomm Stadium', 2, 71283),
    (17338, 20033737, 'FirstEnergy Stadium', 2, 73204),
    (17339, 23017671, 'Borg El-Arab Stadium', NULL, 80000),
    (17386, 20033738, 'M&T Bank Stadium', 2, 74320),
    (17388, 20033740, 'SunLife Stadium', 3, 80120),
    (17390, 20033742, 'Levi\'s Stadium', 3, 75000),
    (17394, 20034500, 'Georgia Dome', 2, 75624),
    (17397, 20034503, 'Alamo Dome', 2, 72000),
    (19621, 29075067, 'Lusail Iconic Stadium', 2, 86250),
    (27339, 47037578, 'Los Angeles Memorial Coliseum', 2, 93607),
    (28837, 56000750, 'Croke Park', NULL, 82300),
    (30439, 67015609, 'Nuevo Mestalla', NULL, 75000),
    (33296, 72018535, 'NRG Stadium', 2, 71738),
    (33297, 72018536, 'AT&T Stadium', 2, 105121),
    (33333, 72022056, 'MetLife Stadium', 2, 82566),
    (33663, 72038733, 'FedEx Field', 3, 91673),
    (33668, 72047297, 'Mercedes-Benz Stadium', 2, 71000),
    (37843, 96022210, '10-lecia', NULL, 71008);

Примеры запросов

SELECT id, fm_id, name, owner_type FROM `stadiums_test` WHERE `capacity` > '70000' ORDER BY `owner_type` DESC LIMIT 40 OFFSET 0;

SELECT id, fm_id, name, owner_type FROM `stadiums_test` WHERE `capacity` > '70000' ORDER BY `owner_type` DESC LIMIT 40 OFFSET 40;
...