10

ダウンロードは、ダウンロード時間、ダウンロード時間ID、およびbunoIDで構成されます。障害は、障害コード、ダウンロード時間ID、ステータス、およびタイプで構成されます。ダウンロードには多くの障害があり、ダウンロード時間IDで参加できます。

一連の障害コードが与えられた場合、結果には、対応する障害カウントを持つ各障害コードが含まれている必要があります。ダウンロードでフォールトコードが見つからない場合は、フォールトカウントをゼロにしてフォールトコードを返す必要があります。

この問題にはOUTERJOINが必要なようですが、LEFTテーブルからnullを含むセットを返さないようであるため、Postgresでこれが期待どおりに機能することは確認されていません。

クエリは以下のとおりですが、簡潔にするためにいくつかの詳細は省略されています。

SELECT  f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM    download_time d 
LEFT OUTER JOIN fs_fault f ON f.downloadtimeid = d.id
    AND f.faultcode IN (1000,1100)
    AND f.statusid IN(2, 4)
WHERE (d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012')
    AND d.bunoid = 166501
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode

翌日、答えを表示するように編集しました。すべての回答は密接であり、さまざまな支援要素がありました。しかし、JayCの答えが最も近いものでした。 これが最終的なSQLであり、フォールトコードのINステートメントをとるWHERE句としての唯一の変更点があります。

SELECT  f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount
FROM    download_time d  
RIGHT OUTER JOIN fs_fault f ON f.downloadtimeid = d.id
        AND f.statusid IN(2, 4)
        AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012'
        AND d.bunoid = 166501
WHERE f.faultcode IN (1000,1100)
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode

ありがとう、すべてあなたの援助に!このサイトが大好きです!

4

4 に答える 4

23

私は他の答えについて重大な疑問を持っているので、答えを出しています。フィルター要件に注意する必要があります。where 句は join の後に実行されることに注意してくださいそのため、外部結合されていないテーブルを参照するwhere 句にフィルター要件がある場合、(多くの状況で) 外部結合を無効にしています。したがって、SQLを取得すると、適切な結合を使用するか、テーブル名を適切に移動してから、フィルター条件をwhere句から結合句に移動するのが最も簡単な解決策のようです。

SELECT  f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM    download_time d 
RIGHT OUTER JOIN fs_fault f ON 
    f.downloadtimeid = d.id
    AND f.faultcode IN (1000,1100)
    AND f.statusid IN(2, 4)
    AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012')
    AND d.bunoid = 166501
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode

同等であるべきだと私が信じている別の方法は

SELECT  f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM    download_time d 
RIGHT OUTER JOIN fs_fault f ON 
    f.downloadtimeid = d.id
    AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012')
    AND d.bunoid = 166501
WHERE
    f.faultcode IN (1000,1100)
    AND f.statusid IN(2, 4)
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode

fs_fault のフィルター要件がどこにあるかは厳密には問題ではありません。(とにかく、SQL エンジンはそれをすべて変更します)。

編集:これは、join 句と where 句でのフィルタリングを示すSQLFiddleです。

于 2012-05-15T00:30:04.897 に答える
2

これにはRIGHT OUTER JOIN. 右の外部結合には、右のテーブルのすべての値が含まNULLれ、左のテーブルにエントリがない場合 (GROUP BYただし、これが機能するかどうかはわかりません...) 、すべての障害コードを含むテーブルの場合。 fs_fault

あなたの場合、fs_faultダウンロードのすべての障害が含まれているようです。これは、予期しない動作の場合でしょうか?

于 2012-05-14T20:11:34.977 に答える
1

左外部結合は、最初のテーブルのすべてに加えて、2 番目のテーブルの一致する行を選択します。最初の表は、ダウンロード試行で構成されているようです。したがって、「from」からの結果には、すべてのダウンロード試行が含まれます。

ただし、必ずしもすべての障害コードが含まれているわけではありません。何が起こっているかというと、基準を満たす 1 つ以上のコードに問題がないということです。

これを機能させるには、すべての障害コードを含むテーブルが必要です。ここでは、最初のテーブルとして障害コードのリストを作成します。次のクエリがこれを行うと思います:

SELECT thefaults.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount
FROM  (select 1000 as faultcode union all select 1100
      ) thefaults join
      fs_fault f
      on f.faultcode = thefaults.faultcode and
         f.statusid in (2, 4) left outer join
      download_time d
      ON f.downloadtimeid = d.id
WHERE (d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012') AND
      d.bunoid = 166501
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

私は認めます: SQL Server 構文を使用して "thefaults" を作成しています。

于 2012-05-14T20:19:09.280 に答える