1

これらのクエリでの無意味なテーブル/列名に対する先制的な謝罪。RemedyのDBバックエンドを使用したことがある場合は、理解できます。

実際の値が20年代のどこかにあると思われるときに、Count Distinctがnull値を返すという問題が発生しています(23、私は信じています)。以下は、一連のクエリとその戻り値です。

SELECT count(distinct t442.c1)
      FROM t442, t658, t631
     WHERE t442.c1 = t658.c536870930
       AND t442.c200000003 = 'Network'
       AND t442.c536871139 < 2
       AND t631.c536870913 = t442.c1
       AND t658.c536870925 = 1
       AND (t442.c7 = 6 OR t442.c7 = 5)
       AND t442.c536870954 > 1141300800
       AND (t442.c240000010 = 0)

結果=497。

テーブルt649を追加し、テーブルt442にリンクされたレコードがあることを確認します。

 SELECT COUNT (DISTINCT t442.c1)
              FROM t442, t658, t631, t649
             WHERE t442.c1 = t658.c536870930
               AND t442.c200000003 = 'Network'
               AND t442.c536871139 < 2
               AND t631.c536870913 = t442.c1
               AND t658.c536870925 = 1
               AND (t442.c7 = 6 OR t442.c7 = 5)
               AND t442.c536870954 > 1141300800
               AND (t442.c240000010 = 0)
               AND t442.c1 = t649.c536870914

結果=263。

列c536870939<=1であるテーブルt649のレコードをフィルターで除外します。

SELECT COUNT (DISTINCT t442.c1)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1

結果=24。

HAVINGステートメントでフィルターします。

SELECT COUNT (DISTINCT t442.c1)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1
        HAVING COUNT (DISTINCT t631.c536870922) =
                                              COUNT (DISTINCT t649.c536870931)

結果=null。

次のクエリを実行すると、結果リストに、どのような種類の戻り値も得られない理由を説明するものが何も表示されません。これは、SELECTからDISTINCTを削除した場合でも当てはまります。(それぞれ25行と4265行のデータが返されます)。

SELECT DISTINCT t442.c1, t631.c536870922, t649.c536870931
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1

null値を返すクエリとまったく同じようにクエリを設定し、完全に正常に機能する場所が他にもいくつかあります。正しい値である使用可能な数値を返します。この状況で一意なものはすべて、実際のクエリではなくデータに関連していると想定する必要がありますが、それを説明するためにデータで何を探すべきかわかりません。集計前に生データでnull値を見つけることができませんでした。他に何がこれを引き起こすのかわかりません。

どんな助けでもいただければ幸いです。

4

5 に答える 5

2

今、私は分かる。元のクエリでの問題は、GROUP BY句なしでHAVING句を使用することは非常に珍しいことです(実際には間違っていませんが)。答えは、クエリのさまざまな部分が実行される操作の順序にあります。

元のクエリでは、次のようにします。

SELECT COUNT(DISTINCT t442.c1)
  FROM ...
 WHERE ...
HAVING COUNT(DISTINCT t631.c536870922) = COUNT(DISTINCT t649.c536870931);

データベースは結合と制約を実行し、その時点で任意のgroupbyおよび集計操作を実行します。この場合、グループ化していないため、COUNT操作はデータセット全体に適用されます。上記で投稿した値に基づいて、COUNT(DISTINCT t631.c536870922)= 25およびCOUNT(DISTINCT t649.c536870931)= 24になります。HAVING句が適用されるようになり、一致するものがなくなります。 set(複数のc1がある場合でも)は等しく、そうではありません。DISTINCTは空の結果セットに適用され、何も取得されません。

あなたが本当にやりたいのは、行数を吐き出す例で投稿したものの単なるバージョンです:

SELECT count(*)
  FROM (SELECT t442.c1     
          FROM t442
             , t658
             , t631
             , t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (   t442.c7 = 6
                OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1
         GROUP BY t442.c1
        HAVING COUNT(DISTINCT t631.c536870922) = COUNT(DISTINCT t649.c536870931)
       );

これにより、631と649のテーブルエントリの数が等しいc1列のリストが表示されます。注:クエリでのDISTINCTの使用には十分注意する必要があります。たとえば、上記の結果を投稿した場合、それは完全に不要です。多くの場合、WHERE句の制約が欠落しているために、希望どおりの結果を返さないクエリのエラーをカバーする一種の壁紙として機能します(「うーん、私のクエリはこれらすべての値の重複を返します。まあ、 DISTINCTはその問題を修正します」)。

于 2009-06-18T18:52:41.977 に答える
1

結果は何ですか:

SELECT COUNT (DISTINCT t631.c536870922),
       COUNT (DISTINCT t649.c536870931)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1

2つの列の値が等しくない場合は、HAVING句を追加すると、結果セットからすべての行が削除されることは理にかなっています。

于 2009-06-18T17:34:28.063 に答える
0

COUNT(DISTINCT column)値をカウントしませんNULL

SELECT  COUNT(DISTINCT val1)
FROM    (
        SELECT  NULL AS val1
        FROM    dual
        )

---
0

それは事実でしょうか?

于 2009-06-18T17:23:47.157 に答える
0

代わりに、HAVING句の条件をWHERE句に入れてみます。HAVINGを選んだ理由はありますか?参考までに、HAVINGは、結果セットが返された後に実行されるフィルターであり、予期しない結果を引き起こす可能性があります。また、クエリの最適化には使用されません。HAVINGを使用する必要がない場合は、使用しないことをお勧めします。

SELECT句にカウントを追加してから、WHERE句でそれらを結合することをお勧めします。

于 2009-06-18T17:33:46.957 に答える
0

私がこれを行う場合:

SELECT distinct t442.c1, count(distinct t631.c536870922), 
    count (distinct t649.c536870931)
          FROM t442, t658, t631, t649
         WHERE t442.c1 = t658.c536870930
           AND t442.c200000003 = 'Network'
           AND t442.c536871139 < 2
           AND t631.c536870913 = t442.c1
           AND t658.c536870925 = 1
           AND (t442.c7 = 6 OR t442.c7 = 5)
           AND t442.c536870954 > 1141300800
           AND (t442.c240000010 = 0)
           AND t442.c1 = t649.c536870914
           AND t649.c536870939 > 1
           group by t442.c1
           having count(distinct t631.c536870922)= 
                         count (distinct t649.c536870931)

カウントする必要のある23行が表示されます。HAVINGステートメントを削除すると、24行が返されます。これは、そのHAVING基準を満たさない余分な行です。

編集:Steve Brobergによる要求に応じて、クエリの結果:

行| t442.c1 | cnt t631 | cnt 649
-------------------------------------------
1 | CHG000000230378 | 2 | 1
2 | CHG000000230846 | 1 | 1
3 | CHG000000232562 | 1 | 1
4 | CHG000000232955 | 1 | 1
5 | CHG000000232956 | 1 | 1
6 | CHG000000232958 | 1 | 1
7 | CHG000000233027 | 1 | 1
8 | CHG000000233933 | 1 | 1
9 | CHG000000233934 | 1 | 1
10 | CHG000000233997 | 1 | 1
11 | CHG000000233998 | 1 | 1
12 | CHG000000233999 | 1 | 1
13 | CHG000000234001 | 1 | 1
14 | CHG000000234005 | 1 | 1
15 | CHG000000234009 | 1 | 1
16 | CHG000000234012 | 1 | 1
17 | CHG000000234693 | 1 | 1
18 | CHG000000234696 | 1 | 1
19 | CHG000000234730 | 1 | 1
20 | CHG000000234839 | 1 | 1
21 | CHG000000235115 | 1 | 1
22 | CHG000000235224 | 1 | 1
23 | CHG000000235488 | 1 | 1
24 | CHG000000235847 | 1 | 1

HAVING句を含めると、最初の行が適切に除外されます。

于 2009-06-18T17:45:01.697 に答える