0

我很难查询。这是在rails(2.1)中,但也许我需要一个find_by_sql。

我有一张公司表,里面有很多客户,有很多组。我需要找到在一定时间内(比如 3 个月)内没有任何客户的公司。

我想出的最好的是:

Company.all(:include => { :clients => :groups },
:conditions => ["(SELECT count(*) FROM groups WHERE
groups.client_id = clients.id AND clients.company_id = companies.id
AND groups.created_at > ?) = 0 AND companies.is_active = 1 AND
clients.is_active = 1", 3.months.ago])

理想情况下,这也会返回为每家公司制作的最后一组的时间(不知道从哪里开始)。为此,我一直在为每家公司使用单独的查询:

Group.last(:include => { :client => :company },
:conditions => { "companies.id" => company.id })

当我运行报告时,我得到的公司在上个月左右创建了组,所以看起来我的初始查询不正确。但我不知道从这里去哪里。

编辑:这是表的表创建语句。我确实删除了大部分字段并留下了相关的内容。我希望这行得通。

mysql> show create table companies;
| Table     | Create Table | | companies | CREATE TABLE `companies` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `created_on` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1646 DEFAULT CHARSET=latin1 |
1 row in set (0.00 sec)

mysql> show create table clients;
| Table   | Create Table | clients | CREATE TABLE `clients` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `company_id` int(11) DEFAULT NULL,
  `created_on` date DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `CompanyID` (`company_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3374 DEFAULT CHARSET=latin1 |
1 row in set (0.00 sec)

mysql> show create table groups;
| Table  | Create Table | groups | CREATE TABLE `groups` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `client_id` int(11) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `ClientID` (`client_id`)
) ENGINE=InnoDB AUTO_INCREMENT=157006 DEFAULT CHARSET=latin1 |
1 row in set (0.00 sec)
4

2 回答 2

0

如果您使用当前的逻辑,您将被迫使用 NOT IN (),方法是选择在过去 3 个月内创建的具有组的所有公司的公司 ID,然后使用 NOT IN () 选择 ID 不在该列表中的公司. 请注意,您根本不需要 count(*) ,因为计数为 0 的记录无论如何都不会存在。NOT IN () 查询通常是个坏主意,因为它们会进行全表扫描。也许最好选择一个 MAX(groups.created_at) 并过滤 MAX(groups.created_at) < 3.months.ago

select c.* from companies c 
inner join clients cl on cl.company_id = c.id 
inner join (select g.client_id from groups g group by g.client_id 
having max(g.created_at) < '2012-06-01') t on t.client_id = cl.id;

这个应该可以工作,并且应该更快一些。或者是这样的:

select c.* from companies c 
inner join clients cl on cl.company_id = c.id 
where cl.id not in (select distinct g.client_id from groups g 
where g.created_at > '2012-06-01');

不确定哪一个对真实数据的表现更好。

于 2012-10-02T20:24:55.310 回答
0

你能尝试一个没有子选择的真正查询吗?

SELECT companies.* FROM companies
 JOIN clients ON clients.company_id = companies.id 
 JOIN groups ON groups.client_id = clients.id
 GROUP BY companies.id
 HAVING MAX(groups.created_at) < '2012-06-01';
于 2012-10-03T00:09:14.767 回答