0

I have a query that is not grouping properly and returning the wrong results and I can't figure out what the problem is.

The query is shown below. FYI - It's not obvious in it's current form why I need the group by because I've removed all other parts of the query to get to the most basic form where I see a problem.

SELECT * FROM (
  SELECT *
  FROM notifications n
  WHERE 1
  --  and group_id = '5b35c8eb075881f8bbdfbcb36b052aa7'
  GROUP BY `from`
) t 
WHERE group_id = '5b35c8eb075881f8bbdfbcb36b052aa7'

The problem is that when I use put the where on the inside subquery (currently commented out), for this case, I end up with 4 results. Each of the 4 results have a different "from" value so should be listed separately. When I put the where on the outside of the subquery I end up with 3 results.

For completeness the table definition is:

CREATE TABLE `notifications` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`mem_id` int(10) unsigned DEFAULT NULL,
`type` varchar(255) NOT NULL,
`from` varchar(255) DEFAULT NULL,
`entry_id` int(11) DEFAULT NULL,
`parent_id` int(11) DEFAULT NULL,
`table_id` varchar(255) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`emailed` tinyint(1) DEFAULT NULL,
`read` tinyint(1) NOT NULL,
`group_id` char(32) NOT NULL,
PRIMARY KEY (`id`),
KEY `mem_id` (`mem_id`),
KEY `created_at` (`created_at`),
KEY `entry_id` (`entry_id`),
KEY `parent_id` (`parent_id`),
KEY `group_id` (`group_id`)
)

Any ideas what could cause this? I'm completely stumped. At this point I'm ready to attribute it to some bug in mysql but that also seems unlikely.


Update

I wasn't clear by what I meant by "wrong results" There were 7 records in the data set with this group_id. There were 2 records with a unique "from" and 5 more records with 2 other "from" ids (one had 3 records, one had 2).

Doing the where for the group by on the inside resulted in in the 4 records that I wanted. I don't care about which row was selected as the result because I'm doing other sums/counts which I excluded from the example because it wasn't directly relevant to the problem.

If I do the where on the outer group by one of the two records with a single "from" did not return at all.
I'll try to update with a sqlfiddle (didn't know about that!) - the issue is that this database I was testing on is wiped daily so I don't have the original data, I'll see if I can reproduce.

update #2

I noticed that in my questions, I've been referring to inner and outer group by - the group by is always on the inner query it's just where the "where" is. I've tried to adjust the phrasing. Again, it's not immediately obvious why I care about the location of the where - but in my final use case, I need the selection to happen on the outside (I'm building a count of notifications that are read/unread and I need a count both per member and total per message - eg the group_id)

sqlfiddle: http://www.sqlfiddle.com/#!2/7d746/5

screenshot of query with inner where:https://www.evernote.com/shard/s48/sh/e355e96e-e48d-4550-bbaf-ffb18bc0bb9c/08e2454867e00e3a05535303429748f1

screenshot of query with outer where:https://www.evernote.com/shard/s48/sh/60b10427-e417-4196-8b92-7d6d8031d21e/c779bc9c46d23472983ac6fa0d25e42d

With the sqlfiddle I get back 4 results each time! Which leads me more to think it's a server issue. We're running MySQL 5.5.28-29.2 Percona Server (GPL), Release rel29.2, Revision 360

4

1 回答 1

2

这个查询:

  SELECT *
  FROM notifications n
  WHERE 1
  GROUP BY `from`

在 ANSI SQL 和几乎所有 DBMS(oracle、postgres、MS SQL 等)上都是错误的。

它仅在 MySql 上运行,因为它们的非标准group by extension
请参阅此链接:http

: //dev.mysql.com/doc/refman/5.0/en/group-by-extensions.html 悬停他们警告某些事情:

但是,这主要在每个未在 GROUP BY 中命名的非聚合列中的所有值对于每个组都相同时很有用。服务器可以从每个组中自由选择任何值,因此除非它们相同,否则选择的值是不确定的。

由于此“功能”,您的查询(从 select * group by 中选择)是不可预测的,结果取决于表中记录的顺序。
看看这个简单的演示:http
: //www.sqlfiddle.com/#!2/b762e/2 这个演示中有两个相同的表,内容相同,唯一的区别是物理行顺序。同样的查询给出完全不同的结果。



----编辑如何解决这个问题-----

要解决查询中的这个问题,只需将两列都添加到 GROUP BY 子句中。

select * FROM (
  SELECT * FROM notifications n
  GROUP BY `from`, `group_id`
) x
WHERE group_id = 'A';

select * FROM (
  SELECT * FROM notifications n
  WHERE group_id = 'A'
  GROUP BY `from`, `group_id`
) x

上面的两个查询对列from和总是给出相同的结果group_id,其他列(不包括在 GROUP BY 子句中)可以是随机的。
看看简单的演示 --> http://www.sqlfiddle.com/#!2/5d19b/5

于 2013-08-29T17:50:45.570 回答