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

副選択なしで実際のクエリを試してみませんか?

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 に答える
0

現在のロジックを使用する場合、過去 3 か月以内に作成されたグループを持つすべての会社の会社 ID を選択して NOT IN () を使用し、次に NOT IN () を使用してそのリストにない ID を持つ会社を選択する必要があります。 . カウントが 0 のレコードは存在しないため、count(*) はまったく必要ないことに注意してください。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 に答える