从MySQL查询中获取关于限制更改的不一致排序结果

从MySQL查询中获取关于限制更改的不一致排序结果,mysql,sql,pagination,codeigniter-2,Mysql,Sql,Pagination,Codeigniter 2,当我增加页面时,我的查询(以下两个)返回不一致的排序结果(例如限制3,3到限制4,3)。请参见下面的示例图像,注意我有两个新项,尽管只将FROM索引更改了1 最糟糕的是,我不能一致地生成任何特定的排序顺序,除了第一组:limit0,6。然后,极限6、6和其他变化会返回截然不同的结果。例如,如果更改“想要”值,则可以获得完全不同的项目集 示例: 环境: SELECT S.*, G.* FROM games C LEFT JOIN songs T ON G.game_id = S.game_id

当我增加页面时,我的查询(以下两个)返回不一致的排序结果(例如限制3,3到限制4,3)。请参见下面的示例图像,注意我有两个新项,尽管只将FROM索引更改了1

最糟糕的是,我不能一致地生成任何特定的排序顺序,除了第一组:limit0,6。然后,极限6、6和其他变化会返回截然不同的结果。例如,如果更改“想要”值,则可以获得完全不同的项目集

示例:

环境:

SELECT S.*, G.* FROM games C LEFT JOIN songs T ON G.game_id = S.game_id WHERE G.game_status != 'deleted' and G.game_status != 'hidden' AND G.group_id = 1 GROUP BY G.game_id ORDER BY ISNULL(G.game_uploading_starts), G.game_listening_starts desc LIMIT 4, 3

SELECT S.*, G.* FROM games C LEFT JOIN songs T ON G.game_id = S.game_id WHERE G.game_status != 'deleted' and G.game_status != 'hidden' AND G.group_id = 1 GROUP BY G.game_id ORDER BY (CASE WHEN G.game_uploading_starts IS NULL then 1 ELSE 0 END), G.game_listening_starts desc LIMIT 4, 3
DROP TABLE IF EXISTS `games`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `games` (
  `game_id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `group_id` mediumint(6) NOT NULL,
  `game_status` enum('playlist','game','compilation','halloffame','theme','deleted','hidden') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'hidden' COMMENT 'except deleted, this is not maintained at runtime, but on a cron job',
  `game_title` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `game_image` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `game_author_id` mediumint(6) NOT NULL,
  `game_ta_id` mediumint(6) DEFAULT NULL,
  `game_winner_id` mediumint(6) DEFAULT NULL,
  `song_id` mediumint(6) DEFAULT NULL COMMENT 'either first example or 1st place song if awarded already',
  `game_buyin` int(11) DEFAULT NULL,
  `game_minpool` int(11) DEFAULT NULL,
  `game_rating_avg` tinyint(3) DEFAULT NULL,
  `game_songs_per_user` tinyint(2) NOT NULL DEFAULT '1',
  `game_uploading_starts` int(10) DEFAULT NULL,
  `game_listening_starts` int(10) DEFAULT NULL,
  `game_rating_starts` int(10) DEFAULT NULL,
  `game_awarding_starts` int(10) DEFAULT NULL,
  `game_uploading_ends` int(10) DEFAULT NULL,
  `game_awarding_complete` int(10) DEFAULT NULL,
  `game_created` int(10) NOT NULL,
  `game_summary` varchar(2000) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`game_id`),
  KEY `game_status` (`game_status`,`song_id`)
) ENGINE=MyISAM AUTO_INCREMENT=37 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;


DROP TABLE IF EXISTS `songs`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `songs` (
  `song_id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `game_id` mediumint(6) NOT NULL,
  `group_id` tinyint(3) NOT NULL,
  `user_id` mediumint(6) NOT NULL,
  `user_vendor_id` tinyint(1) DEFAULT NULL,
  `receipt_id` mediumint(6) DEFAULT NULL,
  `song_status` enum('example','game','playlist','compilation','deleted','winner') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'example',
  `song_title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `song_artist` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `song_album` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_released` smallint(4) DEFAULT NULL,
  `song_genre` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_location` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_reason` varchar(2500) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_image` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_rating_avg` smallint(3) NOT NULL DEFAULT '0',
  `song_adjusted_avg` decimal(5,2) NOT NULL DEFAULT '0.00',
  `song_rated_count` mediumint(6) NOT NULL DEFAULT '0',
  `win_rating` smallint(3) DEFAULT NULL,
  `song_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `song_added` int(11) NOT NULL,
  `song_order` int(4) DEFAULT NULL,
  `song_dedication` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`song_id`),
  KEY `game_id` (`game_id`),
  KEY `user_id` (`user_id`),
  KEY `song_status` (`song_status`)
) ENGINE=MyISAM AUTO_INCREMENT=305 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
  • echo mysql_get_server_info();//5.1.67-log
  • echo PHP_VERSION;//5.4.14
  • 字符集客户端==utf8
  • 字符集连接==utf8
  • 字符集数据库==utf8
  • 字符集文件系统==二进制
  • 字符集结果==utf8
  • 字符集服务器==1
  • 字符集系统==utf8
  • 排序规则\u连接==utf8\u unicode\u ci
  • 排序规则\u数据库==utf8\u unicode\u ci
  • 排序规则\u服务器==拉丁语1\u瑞典语\u ci
  • 我使用的是codeigniter,但我使用的是下面所示的标准sql
  • 在共享主机包上
查询:

SELECT S.*, G.* FROM games C LEFT JOIN songs T ON G.game_id = S.game_id WHERE G.game_status != 'deleted' and G.game_status != 'hidden' AND G.group_id = 1 GROUP BY G.game_id ORDER BY ISNULL(G.game_uploading_starts), G.game_listening_starts desc LIMIT 4, 3

SELECT S.*, G.* FROM games C LEFT JOIN songs T ON G.game_id = S.game_id WHERE G.game_status != 'deleted' and G.game_status != 'hidden' AND G.group_id = 1 GROUP BY G.game_id ORDER BY (CASE WHEN G.game_uploading_starts IS NULL then 1 ELSE 0 END), G.game_listening_starts desc LIMIT 4, 3
DROP TABLE IF EXISTS `games`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `games` (
  `game_id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `group_id` mediumint(6) NOT NULL,
  `game_status` enum('playlist','game','compilation','halloffame','theme','deleted','hidden') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'hidden' COMMENT 'except deleted, this is not maintained at runtime, but on a cron job',
  `game_title` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `game_image` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `game_author_id` mediumint(6) NOT NULL,
  `game_ta_id` mediumint(6) DEFAULT NULL,
  `game_winner_id` mediumint(6) DEFAULT NULL,
  `song_id` mediumint(6) DEFAULT NULL COMMENT 'either first example or 1st place song if awarded already',
  `game_buyin` int(11) DEFAULT NULL,
  `game_minpool` int(11) DEFAULT NULL,
  `game_rating_avg` tinyint(3) DEFAULT NULL,
  `game_songs_per_user` tinyint(2) NOT NULL DEFAULT '1',
  `game_uploading_starts` int(10) DEFAULT NULL,
  `game_listening_starts` int(10) DEFAULT NULL,
  `game_rating_starts` int(10) DEFAULT NULL,
  `game_awarding_starts` int(10) DEFAULT NULL,
  `game_uploading_ends` int(10) DEFAULT NULL,
  `game_awarding_complete` int(10) DEFAULT NULL,
  `game_created` int(10) NOT NULL,
  `game_summary` varchar(2000) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`game_id`),
  KEY `game_status` (`game_status`,`song_id`)
) ENGINE=MyISAM AUTO_INCREMENT=37 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;


DROP TABLE IF EXISTS `songs`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `songs` (
  `song_id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `game_id` mediumint(6) NOT NULL,
  `group_id` tinyint(3) NOT NULL,
  `user_id` mediumint(6) NOT NULL,
  `user_vendor_id` tinyint(1) DEFAULT NULL,
  `receipt_id` mediumint(6) DEFAULT NULL,
  `song_status` enum('example','game','playlist','compilation','deleted','winner') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'example',
  `song_title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `song_artist` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `song_album` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_released` smallint(4) DEFAULT NULL,
  `song_genre` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_location` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_reason` varchar(2500) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_image` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_rating_avg` smallint(3) NOT NULL DEFAULT '0',
  `song_adjusted_avg` decimal(5,2) NOT NULL DEFAULT '0.00',
  `song_rated_count` mediumint(6) NOT NULL DEFAULT '0',
  `win_rating` smallint(3) DEFAULT NULL,
  `song_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `song_added` int(11) NOT NULL,
  `song_order` int(4) DEFAULT NULL,
  `song_dedication` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`song_id`),
  KEY `game_id` (`game_id`),
  KEY `user_id` (`user_id`),
  KEY `song_status` (`song_status`)
) ENGINE=MyISAM AUTO_INCREMENT=305 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
这两个查询都会产生不一致的排序结果,而不是它们之间简单的不同集合

查询表架构:

SELECT S.*, G.* FROM games C LEFT JOIN songs T ON G.game_id = S.game_id WHERE G.game_status != 'deleted' and G.game_status != 'hidden' AND G.group_id = 1 GROUP BY G.game_id ORDER BY ISNULL(G.game_uploading_starts), G.game_listening_starts desc LIMIT 4, 3

SELECT S.*, G.* FROM games C LEFT JOIN songs T ON G.game_id = S.game_id WHERE G.game_status != 'deleted' and G.game_status != 'hidden' AND G.group_id = 1 GROUP BY G.game_id ORDER BY (CASE WHEN G.game_uploading_starts IS NULL then 1 ELSE 0 END), G.game_listening_starts desc LIMIT 4, 3
DROP TABLE IF EXISTS `games`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `games` (
  `game_id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `group_id` mediumint(6) NOT NULL,
  `game_status` enum('playlist','game','compilation','halloffame','theme','deleted','hidden') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'hidden' COMMENT 'except deleted, this is not maintained at runtime, but on a cron job',
  `game_title` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `game_image` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `game_author_id` mediumint(6) NOT NULL,
  `game_ta_id` mediumint(6) DEFAULT NULL,
  `game_winner_id` mediumint(6) DEFAULT NULL,
  `song_id` mediumint(6) DEFAULT NULL COMMENT 'either first example or 1st place song if awarded already',
  `game_buyin` int(11) DEFAULT NULL,
  `game_minpool` int(11) DEFAULT NULL,
  `game_rating_avg` tinyint(3) DEFAULT NULL,
  `game_songs_per_user` tinyint(2) NOT NULL DEFAULT '1',
  `game_uploading_starts` int(10) DEFAULT NULL,
  `game_listening_starts` int(10) DEFAULT NULL,
  `game_rating_starts` int(10) DEFAULT NULL,
  `game_awarding_starts` int(10) DEFAULT NULL,
  `game_uploading_ends` int(10) DEFAULT NULL,
  `game_awarding_complete` int(10) DEFAULT NULL,
  `game_created` int(10) NOT NULL,
  `game_summary` varchar(2000) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`game_id`),
  KEY `game_status` (`game_status`,`song_id`)
) ENGINE=MyISAM AUTO_INCREMENT=37 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;


DROP TABLE IF EXISTS `songs`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `songs` (
  `song_id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `game_id` mediumint(6) NOT NULL,
  `group_id` tinyint(3) NOT NULL,
  `user_id` mediumint(6) NOT NULL,
  `user_vendor_id` tinyint(1) DEFAULT NULL,
  `receipt_id` mediumint(6) DEFAULT NULL,
  `song_status` enum('example','game','playlist','compilation','deleted','winner') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'example',
  `song_title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `song_artist` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `song_album` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_released` smallint(4) DEFAULT NULL,
  `song_genre` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_location` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_reason` varchar(2500) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_image` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `song_rating_avg` smallint(3) NOT NULL DEFAULT '0',
  `song_adjusted_avg` decimal(5,2) NOT NULL DEFAULT '0.00',
  `song_rated_count` mediumint(6) NOT NULL DEFAULT '0',
  `win_rating` smallint(3) DEFAULT NULL,
  `song_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `song_added` int(11) NOT NULL,
  `song_order` int(4) DEFAULT NULL,
  `song_dedication` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`song_id`),
  KEY `game_id` (`game_id`),
  KEY `user_id` (`user_id`),
  KEY `song_status` (`song_status`)
) ENGINE=MyISAM AUTO_INCREMENT=305 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

我假设问题是,您有多行具有相同的
G值。game\u listening\u启动
。这些行可以按任意顺序返回,从一个排序返回到下一个排序

你想要的是稳定的那种。顺序不变的一种。要获得稳定的排序,需要对每一行进行唯一标识。我可以建议:

ORDER BY ISNULL(G.game_uploading_starts), G.game_listening_starts desc, game_id
由于
分组依据
,因此这保证是唯一的

我碰巧认为,在解释稳定排序方面,最有效的方法是:

使用偏移量和 获取时,必须满足以下条件:

基础数据 查询所使用的值不能更改。也就是说,两行中的任何一行 未更新查询中的所有页面请求或查询中的所有页面请求 在单个事务中使用快照或 可序列化事务隔离。如需有关这些的更多信息 事务隔离级别,请参见设置事务隔离级别 (Transact-SQL)

ORDER BY子句包含列或组合 保证唯一的列的数目

我知道您正在使用MySQL,但同样的想法也适用