1

私はこのようなクエリを持っています:

SELECT t1.id,
    (SELECT COUNT(t2.id)
     FROM t2
     WHERE t2.id = t1.id
          ) as num_things
FROM t1
WHERE num_things = 5;

目標は、他のテーブルに5回出現するすべての要素のIDを取得することです。ただし、次のエラーが発生します。

ERROR: column "num_things" does not exist
SQL state: 42703

私はデータベースに少し慣れていないので、おそらくここで何かばかげたことをしているでしょう。アクセスできるようにこのクエリを修正する方法はありますnum_thingsか?または、そうでない場合、この結果を達成する他の方法はありますか?

4

5 に答える 5

10

SQL の使用に関するいくつかの重要なポイント:

  • WHERE 句では列の別名を使用できませんが、HAVING 句では使用できます。それがあなたが得たエラーの原因です。
  • 相関サブクエリを使用するよりも、JOIN と GROUP BY を使用した方がカウントを効率的に行うことができます。それははるかに高速になります。
  • グループをフィルタリングするには、HAVING 句を使用します。

このクエリの書き方は次のとおりです。

SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;

JOINCharles Bretana のソリューションのように、このクエリは t1 をスキップできることに気付きました。しかし、クエリに t1 の他の列を含めたいと思うかもしれません。


Re: コメントの質問:

違いは、グループをグループごとに 1 つの行に減らすWHERE前に、句が行で評価されることです。句は、グループが形成された後に評価されますGROUP BYHAVINGしたがって、たとえば、COUNT()を使用してグループの を変更することはできませんHAVING。グループ自体のみを除外できます。

SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;

上記のクエリではWHERE、条件に一致する行をHAVINGフィルター処理し、カウントが 5 つ以上あるグループをフィルター処理します。

ほとんどの人が混乱するのは、GROUP BYない場合です。HAVINGWHERE

WHERE選択リスト内の式の前に評価されます。SQL 構文では選択リストが最初に配置されるため、これは明らかではない場合があります。WHEREしたがって、 を使用して行を制限することで、多くの高価な計算を節約できます。

SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;

上記のようなクエリを使用すると、select-list の式はすべての行に対して計算されますが、条件のためにほとんどの結果が破棄されHAVINGます。ただし、以下のクエリは、条件に一致する単一の行WHEREに対してのみ式を計算します。

SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;

要約すると、クエリは一連の手順に従ってデータベース エンジンによって実行されます。

  1. によって生成された行を含む、テーブルから行のセットを生成しJOINます。
  2. 行のセットに対して条件を評価WHEREし、一致しない行を除外します。
  3. 行セットのそれぞれについて、select-list の式を計算します。
  4. 列のエイリアスを適用します (これは別の手順です。つまり、select-list の式でエイリアスを使用することはできません)。
  5. GROUP BY句に従って、グループをグループごとに 1 つの行に圧縮します。
  6. グループに対する条件を評価HAVINGし、一致しないグループを除外します。
  7. ORDER BY句に従って、結果を並べ替えます。
于 2009-01-08T22:18:48.893 に答える
3

PostgreSQL では、having 句でエイリアス化された列を使用する方法がないことに言及したいと思います。

すなわち

my_id = 1 を持つユーザーから usr_id を my_id として選択

動作しません。

うまくいかない別の例:

SELECT su.usr_id AS my_id, COUNT(*) AS val FROM sys_user AS su GROUP BY su.usr_id HAVING val >= 1

同じエラーが発生します: val 列が不明です。

これは、Bill Karwin が Postgre に当てはまらないことを書いているためです。

「WHERE句では列のエイリアスを使用できませんが、HAVING句では使用できます。それがエラーの原因です。」

于 2009-07-29T14:37:31.993 に答える
3

他のすべての提案は機能しますが、基本的な質問に答えるには、次のように書くだけで十分です

  SELECT id  From T2
  Group By Id
  Having Count(*) = 5
于 2009-01-08T22:18:51.720 に答える
1

クエリを次のように書き直すことができると思います。

SELECT t1.id
FROM t1
WHERE (SELECT COUNT(t2.id)
     FROM t2
     WHERE t2.id = t1.id
          ) = 5;
于 2009-01-08T22:15:39.587 に答える
0

これを試して

SELECT t1.id,
    (SELECT COUNT(t2.id) as myCount
     FROM t2
     WHERE t2.id = t1.id and myCount=5
          ) as num_things
FROM t1
于 2009-01-08T22:20:57.470 に答える