8

私はSQLをよく知らないので、助けを求めています。

次の図のような統計テーブルのような効果を実現するには、テーブル列からいくつかの値の発生をカウントする必要があります。

必要な結果:

ここに画像の説明を入力してください

コメント:

結果テーブルには、最初の2つの列(contryとsite)が最初のテーブル "Violations"からのものであり、次の5つの列には、Statusテーブルのidの可能な値ごとに "Violations"のstatus_idの発生数(カウント)が含まれている必要があります。

説明:

したがって、既存の2つのテーブルがあります。違反とステータスです。私のsqlfiddleを見てください

違反:

  • id long、
  • 国varchar(20)、
  • サイトvarchar(20)、
  • status_id long、<-これはステータステーブルのステータスのIDです。
  • ...この場合は重要ではない他の列

状態:

  • id long、
  • status long列「status」には、文字列値にマップされる値(1〜4)があります:違反の疑い(1)、違反の確認(2)、違反の確認なし(3)、未決定(4)

私の結合の結果(または1つのテーブル違反のみに基づく)は、列を含む必要があるテーブルを持つことになります:

  • 違反テーブルから:「国」と「サイト」
  • ステータステーブルから:「違反の疑い」、「違反の確認」、「違反の確認なし」、「未決定」、「合計」(この列は違反テーブルでの発生のカウンターです)。

現在のステータスと新しい要件:

以下で最初の試行が行われ(bluefeetのおかげで)、ほぼ完璧です...

select v.country,
v.site,
    SUM(case when s.id = 1 then 1 else 0 end) Total_SuspectedViolations,
    SUM(case when s.id = 2 then 1 else 0 end) Total_ConfirmedViolations,
    SUM(case when s.id = 3 then 1 else 0 end) Total_ConfirmedNoViolations,
    SUM(case when s.id = 4 then 1 else 0 end) Total_NotDetermined,
    COUNT(*) Total
from violations v
inner join status s
    on v.status_id = s.id
group by v.country, v.site

またはJOINなし:

select v.country,
v.site,
    SUM(case when v.status_id = 1 then 1 else 0 end) Total_SuspectedViolations,
    SUM(case when v.status_id = 2 then 1 else 0 end) Total_ConfirmedViolations,
    SUM(case when v.status_id = 3 then 1 else 0 end) Total_ConfirmedNoViolations,
    SUM(case when v.status_id = 4 then 1 else 0 end) Total_NotDetermined,
    COUNT(*) Total
from violations v
group by v.country, v.site

...しかし、あなたがそうあるべき写真で見ることができるように、3つの問題は含まれていません。つまり:

  • 「-すべて-」これは、すべての国の発生をカウントする必要があります
  • 「-不明-」これは、一部の認識されていない国の発生をカウントする必要があります
  • 「-すべて-」(各国に関して)-1つの国内での発生をカウントする必要があります

追加の説明:

  • -Unknown-意味:

Unknownは、たとえばDB Countryテーブルに存在しないか、名前/ IDが間違っている国の発生をカウントする必要があります。そのため、ここでは次のように扱われますUnknown(DBにテーブルがあることを忘れCountryました)。サイトの場合も同様です。サイトの場合、Unknownこれらはステータステーブルに存在する許容値のみであるため、誰かがViolations.status_idに範囲(1〜4)からではなく間違った値を入力したことを意味します。

  • テーブルCountryは次のようになっていると想定できます。

国:

  • id long、
  • 名前varchar(30)

私はそれを行うのに大きな問題があるので、これらの3つの条件を含む正しいSQLクエリを書くのを手伝ってください。

4

2 に答える 2

0

Allの場合は、UNIONステートメントを使用して簡単に実行できます(結果についてはsqlFiddleを参照してください)。

(SELECT v.country,
    v.site,
    SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
    SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
    SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
    SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
    COUNT(*) Total,
    0  'isAll'
FROM violations v
GROUP BY v.country, v.site)
union(
SELECT v.country,
    '- All -',
    SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
    SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
    SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
    SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
    COUNT(*) Total,
  1  'isAll'
FROM violations v
GROUP BY v.country)
UNION (
SELECT '- All -',
    '- All -',
    SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
    SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
    SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
    SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
    COUNT(*) Total,
  1  'isAll'
FROM violations v)
ORDER BY country, isAll DESC, site

ただし、この種のクエリではパフォーマンスがあまり良くない可能性があるため、これが最善の解決策であるとは言えませんが、機能します。

「不明」のバージョン

http://www.sqlfiddle.com/#!2/abfb7/21

(SELECT IF(c.name IS NULL, '- Unknow -', c.name) as name,
    v.site,
    SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
    SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
    SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
    SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
    COUNT(*) Total,
    0  'isAll'
FROM violations v LEFT JOIN country c ON c.name = v.country
GROUP BY c.name, v.site)
union(
SELECT IF(c.name IS NULL, '- Unknow -', c.name) as name,
    '- All -',
    SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
    SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
    SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
    SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
    COUNT(*) Total,
  1  'isAll'
FROM violations v LEFT JOIN country c ON c.name = v.country
GROUP BY c.name)
UNION (
SELECT '- All -',
    '- All -',
    SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
    SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
    SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
    SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
    COUNT(*) Total,
  1  'isAll'
FROM violations v LEFT JOIN country c ON c.name = v.country)
ORDER BY name, isAll DESC, site
于 2013-03-12T12:28:38.973 に答える
0

あなたを使用with rollupすると、あなたが望む必要な合計フィールドが得られます

select v.country,
v.site,
SUM(case when s.id = 1 then 1 else 0 end) Total_SuspectedViolations,
SUM(case when s.id = 2 then 1 else 0 end) Total_ConfirmedViolations,
SUM(case when s.id = 3 then 1 else 0 end) Total_ConfirmedNoViolations,
SUM(case when s.id = 4 then 1 else 0 end) Total_NotDetermined,
COUNT(*) Total
from violations v
     inner join status s
     on v.status_id = s.id
group by v.country, v.site WITH ROLLUP

お役に立てれば

ドキュメントwith rollup

フィドル

于 2013-03-12T12:30:26.197 に答える