2

国、地域、都市、通りなど、場所を特定できるオブジェクトを表す「things」と呼ばれる比較的大きな(> 10 ^ 6エントリのような)テーブルがあります。これらは固定された深さのオブジェクトのツリーとして使用されるため、テーブル構造は次のようになります。

id
name
type
continent_id
country_id
city_id
area_id
street_id
etc.

「things」内の関連付けは1:nです。つまり、通りまたはエリアは常に定義された都市と国に属します(2つまたはまったくない)。たとえば、列city_idには、その都市内にあるすべてのオブジェクトの「都市」のもののIDが含まれています。「type」列には、文字列としてモノのタイプ(Street、Cityなど)が含まれます。

このテーブルは、別のテーブル「actions」で「thing_id」として参照されます。特定の場所でのアクティブおよび非アクティブなアクションの数を示すアクション場所統計のテーブルを生成しようとしています。のような単純なJOIN

SELECT count(nullif(actions.active、1))AS icount、
       count(nullif(actions.active、0))AS acount、
       things.name AS名、things.id AS things_id、things.city_id AS city_id
  FROM「アクション」
  左は、actions.thing_id=things.idで物事に参加します
 WHERE UPPER(substring(things.name、1、1))= UPPER('A')
   およびactions.datetime_atBETWEEN'2012-09-26 19:52:14' AND '2012-10-26 22:00:00'
 GROUP BY things.name、things.id ORDER BY things.name

アクションが関連付けられている「もの」(「A」で始まる)のリストと、次のようなアクティブおよび非アクティブのカウントが表示されます。

icount | acount | name                      | thing_id | city_id
------------------------------------------------------------------
     0        5   Brooklyn, New York City   | 25       | 23
     1        0   Manhattan, New York City  | 24       | 23
     3        2   New York City             | 23       | 23

今私はしたい

  • 「都市」のものだけを考慮し(簡単です。「もの」を入力してフィルタリングします)、
  • アクティブ/非アクティブカウントでは、アクションが都市自体に関連付けられているか、都市の何かに関連付けられているか(=同じcity_idを持つ)に関係なく、この都市で発生するすべてのアクションの合計を使用します。上記と同じデータセットを使用すると、新しいクエリの結果は次のようになります。
icount | カウント| 名前| things_id | city_id
-------------------------------------------------- --------------------------------
     47ニューヨーク市| 23 | 23

このテーブルのthing_idは必要ありません(とにかく一意ではないため)が、都市の名前(表示用)が必要なので、IDも出力するのはおそらく同じくらい簡単であり、私のコードをできるだけ変更します。

これを実現するには、上記のクエリをどのように変更する必要がありますか?可能であれば、データベースへの追加のアクセスや、プロシージャ、トリガー、ビュー、一時テーブルなどの高度なSQL機能を避けたいと思います。

Rails3.0.14(Mac OS X 10.7.4)でRuby1.9.3とともにPostgres8.3を使用しています。

ありがとうございました!:)

4

1 に答える 1

2

独立したサブクエリで市内のすべてのものに対するアクションをカウントしてから、限られたもののセットに参加する必要があります。

SELECT c.icount
      ,c.acount      
      ,t.name
      ,t.id AS thing_id
      ,t.city_id
FROM  (
   SELECT t.city_id
         ,count(nullif(a.active, 1)) AS icount
         ,sum(a.active) AS acount
   FROM   things t 
   LEFT   JOIN actions a ON a.thing_id = t.id 
   WHERE  t.city_id = 23           -- to restrict results to one city
   GROUP  BY t.city_id
   ) c                             -- counts per city
JOIN   things t USING (city_id)
WHERE  t.name ILIKE 'A%'
AND    t.datetime_at BETWEEN '2012-09-26 19:52:14'
                         AND '2012-10-26 22:00:00'
ORDER  BY t.name, t.id;

また、クエリ内の他の多くのことを簡略化し、読みやすくするためにテーブルエイリアスを使用しました。

于 2012-09-26T22:00:18.187 に答える