web-dev-qa-db-ja.com

COALESCE関数がこのクエリに対して機能しないのはなぜですか?

サブクエリから取得される列の数を数えようとしていますが、一部のサブクエリが空である可能性があります。空のセルとして表示するのではなく、0にしたいのです。COALESCE関数を使用してこれを実行できることがわかりましたが、たとえば、次のクエリでは空のセルが返されます。

CREATE VIEW third_table AS 
SELECT * 
FROM  (second_table  
NATURAL FULL JOIN (
   SELECT assignment_id, COALESCE( count(*), 0 ) AS num_60_79 
   FROM (
      SELECT assignment_id, mark_as_percent 
      FROM avg_required_table
      WHERE mark_as_percent >= 60 
      AND mark_as_percent < 80
      ) a 
   GROUP BY assignment_id
   ) b);

これはCOALESCEの使用方法ですか?

3
Mathu

あなたの答えに質問

COALESCE全く無意味 =最初に配置した場所。集約関数count()neverはNULLを返します。また、ロジックは、サブクエリでnum_60_79が1未満になることはないことを示しています。関連:

しかし、それは無関係です。サブクエリが行なしを返す場合、値を返すことができないためです。まったく。

正確には、サブクエリは任意の数の行を返す可能性がありますが、second_tableに結合するときに、(assignment_id, num_60_79)に一致する値を持つ行がない場合、サブクエリのすべての列bは代わりにNULL値で埋められます。関連:

NATURAL FULL JOIN非常にエキゾチックテーブルを結合する方法です。特に、まだCOALESCEの使い方を学んでいる人にとっては。 マニュアルの引用:

NATURALは、同じ名前を持つ2つのテーブルのすべての列を示すUSINGリストの省略形です。

そして:

FULL OUTER JOINは、結合されたすべての行に加えて、一致しない左側の行ごとに1行(右側にnullが続く)と、一致しない右側の行ごとに1つの行(左側にnullがある)を返します。

num_60_79second_tableという名前のnoという名前の列があると想定しても安全だと思います。結合条件があったとしても、それを結合条件に含めたくはないでしょう。列assignment_idだけを結合したいので、これをNATURALキーワードの代わりにクエリに入れます。

また、ここではFULL JOINは理論的にはpossibleですが、通常はLEFT JOINが表示されます。

また、クエリに2層のサブクエリやその他のノイズも必要ありません。

適切なクエリ

あなたがいる間すべてのことを考えました...

サブクエリから取得された列の数を数えようとしています

...私の教育を受けた推測は代わりにこのクエリが欲しいです:

SELECT s.*, COALESCE(b.num_60_79, 0) AS num_60_79
FROM   second_table s
LEFT   JOIN (
   SELECT assignment_id, count(*) AS num_60_79 
   FROM   avg_required_table
   WHERE  mark_as_percent >= 60 
   AND    mark_as_percent <  80
   GROUP  BY assignment_id
   ) b USING (assignment_id);
4

レベルを上げる

より正しい形:

SELECT 
   col1, 
   .. 
   colx, 
   COALESCE(num_60_79,0) as num_60_79,
   ... colY
   FROM (second_table 
          NATURAL FULL JOIN (SELECT assignment_id,  count(*) AS num_60_79 
                             FROM (SELECT assignment_id, mark_as_percent 
                                   FROM avg_required_table
                                   WHERE mark_as_percent >= 60 
                                   AND mark_as_percent < 80) a 
                             GROUP BY assignment_id) b);

列のリストの*を変更しても、機能しないという意味ではありませんが、フォームがより正確になります。

1
a_vlad