繁体   English   中英

在MySQL SELECT中使用LIMIT更改ORDER BY运算符会产生不一致的行集

[英]Changing ORDER BY caluse with LIMIT in MySQL SELECT gives inconsistent set of rows

我很惊讶今天从以下MySQL查询中发现不一致的结果:

SELECT Research.Focus, Research.Media, Country.Name, GROUP_CONCAT(DISTINCT AskMethod.Name ORDER BY ResearchAskMethod.MethodID SEPARATOR ', ') as AskMethodName, Research.ResearchDate, Research.ResearchID FROM AskMethod INNER JOIN ((Country INNER JOIN Research ON Country.CountryID = Research.CountryID) INNER JOIN ResearchAskMethod ON Research.ResearchID = ResearchAskMethod.ResearchID) ON AskMethod.MethodID = ResearchAskMethod.MethodID WHERE Research.ResearchID=ResearchAskMethod.ResearchID AND Research.ResearchDate=1996 GROUP BY Research.ResearchID ORDER BY Country.Name, Research.Media, AskMethodName, Research.ResearchDate DESC LIMIT 0, 5;

该查询给了我5行: ResearchID :18、17、10、7、13。

如果我只是将DESC添加到第一个ORDER BY参数,则它变为:

...ORDER BY Country.Name DESC, Research.Media...

该查询为我提供了不同的5行集: ResearchID :8、14、9、13、7

ResearchIDResearch表的主键。

如果我只是更改ORDER BY参数的顺序,它也会给我一个不同的集合,例如:

... ORDER BY Research.Media, Country.Name, AskMethodName...

您能帮我了解发生了什么吗?

下面由@Kiley回答,这是固定查询:

SELECT * 
FROM (
    SELECT Research.Focus, Research.Media, Country.Name, GROUP_CONCAT( DISTINCT ValMethod.Name
    ORDER BY ResearchValMethod.MethodID
    SEPARATOR  ', ' ) AS ValMethodName, Research.ResearchDate, Research.ResearchID
    FROM ValMethod
    INNER JOIN (
        (
        Country
        INNER JOIN Research ON Country.CountryID = Research.CountryID
        )
    INNER JOIN ResearchValMethod ON Research.ResearchID = ResearchValMethod.ResearchID
    ) ON ValMethod.MethodID = ResearchValMethod.MethodID
    WHERE Research.ResearchID = ResearchValMethod.ResearchID
    AND Research.ResearchDate = 1996
    GROUP BY Research.ResearchID
    ORDER BY Country.Name, Research.Media, ValMethodName, Research.ResearchDate
) AS Result
ORDER BY Result.Name, Result.Media, ValMethodName, Result.ResearchDate DESC

我在这里的回答主要是针对SQL Server,但该概念也适用于MySQL。 如果您对此表示怀疑,则应运行我的测试并亲自进行验证。

我认为这里的问题是,您希望按ResearchDate的顺序排列前五个结果,然后再按降序对THOSE进行排序。 根据PinalDave的说法SELECT TOP X子句(与LIMIT的功能的子集等效)在SELECT查询的逻辑处理中是FINAL步骤,因此在对结果进行ORDER运算后,它将获取第一个X

如果您对处理顺序感到好奇,可以在《 MySQL参考手册》上找到:

HAVING子句几乎是最后一次应用,即将项目发送到客户端之前,没有进行优化。 (HAVING之后应用限制。)

这是一个简单的示例,将演示我认为您遇到的问题以及解决方法:

CREATE TABLE [Test] (
    Number INT PRIMARY KEY
);

INSERT INTO [Test] VALUES (1);
INSERT INTO [Test] VALUES (2);
INSERT INTO [Test] VALUES (3);
INSERT INTO [Test] VALUES (4);
INSERT INTO [Test] VALUES (5);
INSERT INTO [Test] VALUES (6);
INSERT INTO [Test] VALUES (7);
INSERT INTO [Test] VALUES (8);
INSERT INTO [Test] VALUES (9);
INSERT INTO [Test] VALUES (10);

这样就可以设置您的数据了。 现在运行以下查询并检查输出:

SELECT TOP 5 * FROM Test ORDER BY Number;

在MySQL中:

SELECT * FROM Test ORDER BY Number LIMIT 5;

该查询将产生以下结果集:

1
2
3
4
5

现在,在这里查看区别:

SELECT TOP 5 * FROM Test ORDER BY Number DESC;

在MySQL中:

SELECT * FROM Test ORDER BY Number DESC LIMIT 5;

产生:

10
9
8
7
6

注意结果集不同吗? 这就是您现在遇到的问题。 相反,您需要做的是在子查询中选择所需的结果,然后在外部查询中对THOSE进行排序。

SELECT * FROM (
    SELECT TOP 5 * FROM Test ORDER BY Number
) AS MyTest ORDER BY Number DESC

最后,在MySQL中:

SELECT * FROM (
    SELECT * FROM Test ORDER BY Number LIMIT 5
) AS MyTest ORDER BY Number DESC

结果?

5
4
3
2
1

我想这就是您要寻找的。

我不是MySQL专家,但我还发现了LIMIT的一些巧妙功能,可让您指定返回结果集的上限和下限,因此,如果您确切知道表中预期有多少行(您可能不知道t,但我认为这可能值得您理解),您可能会这样(仅MySQL示例:)

SELECT * FROM Test ORDER BY Number DESC LIMIT 6, 10

我将按照下面提供的示例来固定您的查询,但是由于它的格式有些欠妥,因此很难判断到底发生了什么……:

SELECT * FROM (SELECT Research.Focus, Research.Media, Country.Name, GROUP_CONCAT(DISTINCT AskMethod.Name ORDER BY ResearchAskMethod.MethodID SEPARATOR ', ') as AskMethodName, Research.ResearchDate, Research.ResearchID FROM AskMethod INNER JOIN ((Country INNER JOIN Research ON Country.CountryID = Research.CountryID) INNER JOIN ResearchAskMethod ON Research.ResearchID = ResearchAskMethod.ResearchID) ON AskMethod.MethodID = ResearchAskMethod.MethodID WHERE Research.ResearchID=ResearchAskMethod.ResearchID AND Research.ResearchDate=1996 GROUP BY Research.ResearchID ORDER BY Country.Name, Research.Media, AskMethodName, Research.ResearchDate) AS Result ORDER BY Country.Name, Research.Media, AskMethodName, Research.ResearchDate DESC

作为记录,我建议稍微清理一下查询的布局,以使它们更易于理解。 就像在PHP或C#或Java或C ++或任何其他编程语言中一样,使用换行符,空白间距等来提高代码的可读性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM