-2

我有以下查询,它返回 250 条记录:

SELECT DISTINCT p.* FROM Persons AS p
                      INNER JOIN Colors AS c ON c.ColorId = p.FavoriteColorId 
WHERE p.Name = 'John Doe' AND c.ColorName IN ('RED','BLUE','YELLOW')
                      LIMIT 240,10;

-- Returns 198 records
SELECT DISTINCT p.* FROM Persons AS p
                      INNER JOIN Colors AS c ON c.ColorId = p.FavoriteColorId 
WHERE p.Name = 'John Doe' AND c.ColorName IN ('RED','BLUE','YELLOW')

-- Returns 250 records. Why?
SELECT DISTINCT COUNT(*) FROM Persons AS p
                      INNER JOIN Colors AS c ON c.ColorId = p.FavoriteColorId 
WHERE p.Name = 'John Doe' AND c.ColorName IN ('RED','BLUE','YELLOW')

当我执行上述操作时,即使总共有 250 条记录,我也看不到任何记录。LIMIT当我将 更改为时,它才开始返回记录LIMIT 197,10,然后我看到 1 条记录。

为什么会这样?

4

3 回答 3

1

你在错误的地方有不同的计数。您计算所有行 (250) 并选择不同的行值。只有 1 行,即 250。

你的意思是 select count(distinct p.*) 然后返回 198

于 2013-08-02T22:38:26.353 回答
0

我已经重新阅读了这个问题,我不清楚哪些查询返回了什么。

我们的期望:

  • 第一个查询:没有返回行(只有 198 个不同的行,没有 240 行要跳过)

  • 第二个查询:返回 198 行,听起来很合理

  • 第三个查询:返回 1 行,值为 250,这也是合理的。

如果这是您所看到的行为,那么这一切都在意料之中。

DISTINCT 运算符消除了重复行,这解释了 198 和 250 之间的差异。并且由于 LIMIT 作为执行计划中的最后一步(或几乎最后一步)应用,这解释了为什么第一个查询没有返回任何行。

要获取第二个查询返回的 198 行的计数,一种简单的方法是将第二个查询(返回 198 行)包装在另一个从中获取 COUNT 的查询中。

SELECT COUNT(1) AS mycount
  FROM (
         SELECT DISTINCT p.*
           FROM Persons p
           JOIN Colors c
             ON c.ColorId = p.FavoriteColorId
            AND c.ColorName IN ('RED','BLUE','YELLOW')
          WHERE p.Name = 'John Doe'
       ) q

如果您想计算表中的行数Persons,而不消除 Persons 表中的任何重复项,那么获得它的一种方法是:

SELECT COUNT(1) AS mycount
  FROM Persons p
 WHERE p.Name = 'John Doe'
   AND EXISTS ( SELECT 1 
                  FROM Colors c
                 WHERE c.ColorName IN ('RED','BLUE','YELLOW')
                   AND c.ColorId = p.FavoriteColorId
              )

如果您在 Persons 表中有一个 UNIQUE 且 NOT NULL 的列,例如 an id INT PRIMARY KEY,您可以这样做:

SELECT COUNT(DISTINCT p.id) AS mycount
  FROM Persons p
  JOIN Colors c 
    ON c.ColorName IN ('RED','BLUE','YELLOW')
   AND c.ColorId = p.FavoriteColorId
 WHERE p.Name = 'John Doe'

原始答案

第一个查询应该返回不超过 10 行。

您报告第二个查询返回 198 行。如果这是真的,我看不到第一个查询(除了添加 LIMIT 子句之外与此相同)应该如何返回任何行。

第三个查询应该返回一行。

您看到的结果没有很好的解释。

Q您能否在 msyql 命令行客户端中复制此行为,以排除您正在使用的客户端应用程序中的行为。

Q你运行的是什么版本的 MySQL?(这可能是您的 MySQL 版本中的错误。)

Q这些表使用什么引擎(MyISAM、InnoDB)?

Q您是否验证过您的表格与CHECK TABLE tablename EXTENDED?

:并且您已经确认在您的查询运行时其他进程没有插入、更新和/或删除行?

您的第一个查询有点奇怪,因为它指定了一个LIMIT子句,但是没有GROUP BYorORDER BY子句或任何其他规定应该以什么顺序返回行的内容。

第三个查询有点奇怪,因为DISTINCT不需要关键字。如果没有GROUP BY子句,我们希望SELECT COUNT(*)返回一行。

我的一部分质疑观察到的行为的报告是否准确。第三个查询真的返回 250 行,还是返回单行,计数值为 250?(这是两个非常不同的东西。)

在运算符消除重复行的情况下,我们通常期望 aSELECT COUNT(*)返回的值大于返回的行数。SELECT DISTINCT p.*DISTINCT

于 2013-08-02T22:01:25.070 回答
0

默认情况下,顺序是ASC

尝试颠倒顺序并仅获得 10 条这样的记录

     Order by RAND ()  LIMIT 10

没有 ORDER BY,就没有默认的排序顺序。 因此,如果您没有指定顺序,那么它是随机的,那么您可以简单地限制 10 条记录而不设置位置 240。

编辑:

 SELECT  COUNT(*) as counts FROM Persons AS p
                  INNER JOIN Colors AS c ON c.ColorId = p.FavoriteColorId 
 WHERE p.Name = 'John Doe' AND c.ColorName IN ('RED','BLUE','YELLOW')
 GROUP BY c.Id ORDER BY c.Id LIMIT 240,10
于 2013-08-02T20:12:56.077 回答