2011-01-04 3 views
0

は少し検索して読んだ後、私は自分のアプリケーションのための次のSQLクエリを思い付いた:OracleでこのSQLクエリを簡略化するにはどうすればよいですか?

SELECT 
    ROUND(AVG(CASE WHEN gender = 'M' THEN rating END), 1) avgAllM, 
    COUNT(CASE WHEN gender = 'M' THEN rating END) countAllM, 
    ROUND(AVG(CASE WHEN gender = 'F' THEN rating END), 1) avgAllF, 
    COUNT(CASE WHEN gender = 'F' THEN rating END) countAllF, 
    ROUND(AVG(CASE WHEN gender = 'M' AND UserAge(birth_date) <= 18 THEN rating END), 1) avgU18M, 
    COUNT(CASE WHEN gender = 'M' AND UserAge(birth_date) <= 18 THEN rating END) countU18M, 
    ROUND(AVG(CASE WHEN gender = 'F' AND UserAge(birth_date) <= 18 THEN rating END), 1) avgU18F, 
    COUNT(CASE WHEN gender = 'F' AND UserAge(birth_date) <= 18 THEN rating END) countU18F 
FROM movie_ratings mr INNER JOIN accounts a 
    ON mr.aid = a.aid 
WHERE mid = 5; 

そして、私は可能であればどのように私は、これを簡略化することができます思ったんだけど。 birth_dateフィールドのタイプはDATEであり、UserAgeはその日付フィールドからの年齢を計算する関数です。次のように

テーブル構造は以下のとおりです。

[ACCOUNTS] 
aid(PK), birth_date, gender 

[MOVIE_RATINGS] 
mid(PK), aid(PK,FK), rating 

私は二つのことを探しています:それより経験のあるユーザ上記のコードに

  • 一般的な単純化私はそうではないことを知っています。
  • 私はPHPでこれをやっていますが、レコードごとにこれらの変数をすべて持つ連想配列があります。私はそれらを多次元配列にグループ化する方法を探しているので、PHPコードは読みやすくなります。もちろん、私はPHP自体でこれをやりたがりません。無意味です。例えば

、このような何か:これが可能であれば私も知らないので、それがある場合、私は本当に思ったんだけど

$info['avgAllM'] 
$info['countAllM'] 
$info['avgAllF'] 
$info['countAllF'] 
$info['avgU18M'] 
$info['countU18M'] 
$info['avgU18F'] 
$info['countU18F'] 

$info[0]['avgAllM'] 
$info[0]['countAllM'] 
$info[1]['avgAllF'] 
$info[1]['countAllF'] 
$info[2]['avgU18M'] 
$info[2]['countU18M'] 
$info[3]['avgU18F'] 
$info[3]['countU18F'] 

の代わりにどのようにそれを行うことができます。

なぜこのすべてが欲しいですか?上記のSQLクエリは、必要な完全なSQLの断片です。すべての作業を行う前に、同じ結果を得るためのよりコンパクトなSQLクエリがあるかどうかを知りたいからです。基本的には、上記のようないくつかの行を追加しますが、異なる条件、特に日付の行を追加します。

+0

テーブル構造の詳細がなければ、なぜmid = 5にフィルタリングするwhere節がありますか?あなたは本当に何を達成しようとしていますか?あなたの多次元配列のために、SQLヘルプのグループではないでしょうか? – clyc

+0

私は本当に関連性があるとは思わないが、テーブル構造で更新しました。私はGROUP BYをどのように使うことができるのかよくわかりません... –

答えて

3

あなたは少し物事を単純化する可能性があることを

SELECT ROUND(AVG(AllM), 1) avgAllM, 
     COUNT(AllM)   countAllM, 
     ROUND(AVG(AllF), 1) avg, 
     COUNT(AllF)   countAllF, 
     ROUND(AVG(U18M), 1) avgU18M, 
     COUNT(U18M)   countU18M, 
     ROUND(AVG(U18F), 1) avgU18F, 
     COUNT(U18F)   countU18F 
FROM yourview 

から選択し次のように定義されたVIEW

SELECT 
     CASE WHEN gender = 'M' THEN rating END AS AllM, 
     CASE WHEN gender = 'F' THEN rating END AS AllF, 
     CASE WHEN gender = 'M' AND UserAge(birth_date) <= 18 THEN rating END AS U18M, 
     CASE WHEN gender = 'F' AND UserAge(birth_date) <= 18 THEN rating END AS U18F 
     FROM movie_ratings mr INNER JOIN accounts a 
     ON mr.aid = a.aid 
     WHERE mid = 5 

を作成することができますか?

+0

私はビューについてはあまりよく分かりませんが、WHERE句は変数に依存しているため不可能であると私は信じています。 5 'という、それは単なる例でした。 –

+0

あなたが投稿したものを編集してSELECTに「mid」フィールドを挿入し、WHERE句を他の選択に移動したビューについてもう少し分かりましたが、うまくいくようです。私は、誰かがより良い方法を提供したり、この場合のビューに対して良い議論をしない限り、これを正しい答えとして受け入れます。 –

+0

PHPの部分はどうですか? –

0

これは、あまりに早く最適化を行う場合に過ぎません。クエリは必要な処理を行い、実際には複雑であるため、私は、必然的に役立つことがあるとは確信していません。おそらくあなたのデータの特性に依存します。クエリは遅いですか?それが速くなると思いますか?

次のように並べ替える価値があります。すべての条件はACCOUNTSテーブルに依存しているので、私が想定しているテーブルはMOVIE_RATINGSテーブルよりも大幅に小さくなりますが、より小さなデータセットですべての計算を行うことができます。一度に1つのムービー(mid = 5)だけを選択しているのであれば、おそらくそうではありません。

私はこれがうまくいくとは思っていませんが、それはすべきだと思います。

SELECT 
    ROUND(AVG(rating * AllM), 1) avgAllM, 
    COUNT(rating * AllM) countAllM, 
    ROUND(AVG(rating * AllF), 1) avgAllF, 
    COUNT(rating * AllF) countAllF, 
    ROUND(AVG(rating * AllM * U18), 1) avgU18M, 
    COUNT(rating * AllM * U18) countU18M, 
    ROUND(AVG(rating * AllM * U18), 1) avgU18F, 
    COUNT(rating * AllM * U18) countU18F 
FROM 
    movie_ratings mr 
    INNER JOIN (
    select 
     aid, 
     case when gender = 'M' then 1 end as AllM, 
     case when gender = 'F' then 1 end as AllF, 
     case when UserAge(birth_date) <= 18 then 1 end as U18 
    from accounts) a ON mr.aid = a.aid 
WHERE mid = 5; 

残念ながら、私はおそらくあなたが持っているままにしておきます。あなたが持っているクエリは理解しやすく、おそらくかなり良い結果を示します。

+0

Martinが提案したVIEWメソッドを使用しない理由は何ですか? –

+0

ところで:私はビューを使用することは決して最適化ではないとは思わなかった。 OPは簡略化について尋ねた。私が知っている限り、いずれの方法でもパフォーマンスに影響はありません。 –

+0

まあ、それはすべてあなたが達成しようとしているものに依存すると思います。私が言ったように、私はあなたが持っていた元のクエリはとにかくかなり良いと思います。ビューには、このタイプのすべてのクエリで使用できる一貫した定義を提供するという利点があります。 –

関連する問題