2016-04-05 25 views
-1

私のデータベースを含むCOUNTのAVGを含むクエリとクエリはそうのようになります。SQLクエリの日付

PEAK(NAME、ELEV、DIFF、MAP、REGION)
CLIMBER(NAME、SEX)
は(TRIP_ID、NAME)
登っ(TRIP_ID、PEAK)

    に参加しました210
  • PEAKは、ユーザーが興味を持っている山のピークに関する情報を表示します。表には、各ピークの名前、標高(フィート単位)、難易度(1-5のスケール)、マップその上に位置するシエラネバダの地域にあります。
  • CLIMBERはクラブのメンバーを列挙し、その氏名と性別を示しています。
  • 参加者は、さまざまな登山旅行のそれぞれに参加した登山者の集合を提供します。各旅行の参加者の数は様々です。
  • CLIMBEDは、各ピークが登ったデータに沿って、各登山旅行でどのピークが登ったかを示します。

私はこれら2例のシナリオのためのSQLクエリを書く/ wの助けを必要とする:

  • クラブの男性で、クラブの女性でスケーリングピークの平均数を計算します。
  • マリアが登ったひとつひとつのピークをどんな人が登っていますか?
  • 60日間のピーク期間に20以上のピークに達したのは誰ですか?

EDIT:まずクエリが機能するようになりましたし、次のようになります。

SELECT SEX, AVG(num_peaks) AS avg_peaks 
FROM 
    (
    SELECT CLIMBER.*, COUNT(CLIMBED.PEAK) num_peaks 
    FROM CLIMBED 
    INNER JOIN PARTICIPATED 
    ON PARTICIPATED.TRIP_ID = CLIMBED.TRIP_ID 
    RIGHT OUTER JOIN CLIMBER 
    ON CLIMBER.NAME = PARTICIPATED.NAME 
    GROUP BY CLIMBER.NAME, CLIMBER.SEX 
) 
GROUP BY SEX; 

このクエリでは、ピークの全体数は、私の男性を登った私を与え、メス。しかし、私はカウントの代わりに平均を得る方法を理解しているように見えることはできません。私はあなたが単にAVG b/cにCOUNT機能を変更することはできません知っている私のデータは整数ではなく文字列形式です。

私の2番目のクエリはそうのようになります。

SELECT DISTINCT PARTICIPATED.NAME 
FROM PARTICIPATED 
INNER JOIN CLIMBED 
ON PARTICIPATED.TRIP_ID = CLIMBED.TRIP_ID 
WHERE CLIMBED.PEAK IN 
    (
    SELECT CLIMBED.PEAK 
    FROM CLIMBED 
    INNER JOIN PARTICIPATED 
    ON PARTICIPATED.TRIP_ID = CLIMBED.TRIP_ID 
    WHERE NAME IN ('MARIA') 
    ) 
AND PARTICIPATED.NAME NOT IN ('MARIA'); 

クエリは私にマリアも登ったピークを登ってきた人たちのすべてを与えるが、私にを登ってきたばかりの人を与えるものではありませんすべてマリアが登った単一のピーク。この方法で残りの人をフィルタリングする方法がわからない。

そして最後に、私の最後のクエリはそうのようになります。

SELECT PARTICIPATED.NAME, COUNT(DISTINCT CLIMBED.PEAK) 
FROM PARTICIPATED 
LEFT JOIN CLIMBED 
ON CLIMBED.TRIP_ID = PARTICIPATED.TRIP_ID 
GROUP BY PARTICIPATED.NAME; 

このクエリは、登山者の名前と彼らはそれぞれが登っていたピークの合計数のすべてを与えますが、私はそれをフィルタリングする方法について見当もつかない60日以内に20以上のピークを登った人のみが表示されます。 私は使用しようとしました

HAVING CLIMBED.WHEN BETWEEN -60 AND 60; 

しかし、それは動作しません。

ご協力いただきありがとうございます。私はOracle Expressをデータベースとして使用しています。

+1

あなたは既にこの質問を投稿しています[こちら](http://stackoverflow.com/questions/36437653/sql-query-average-climbed-and-pair-that-has-climbed-themost-peaks) – MT0

+0

あなたの全体の質問に対する回答ではありません。しかし、2番目のクエリは 'WHERE CLIMBED.PEAK = ALL(... WHERE NAME = 'MARIA')と名前<> 'MARIA' 'を持つ必要があります。 'IN'を使うのは= ANY(...)と同じですが、1つではなく、すべてのピークが必要です。また、単一の値にINを使用するのは無意味ですが、代わりに=と<>を使用してください。あなたにはセミコロンが余分にあります。 [この記事ORACLEとANY、ALL、およびSOME](https://oracle-base.com/articles/misc/all-any-some-comparison-conditions-in-sql)を参照してください。 –

答えて

0

私はSQLサーバーで作業していますので、インターネットでOracle構文を検索しましたが、いくつかのエラーがあるかもしれませんが、それは問題ないと思います。

あなたの最初のクエリについて、私の考えは、各参加者が登ったピークの数を数えることになるサブクエリを行い、次に各セックスの平均を取ることです。サブクエリを分離するために、私はwith構文をできるだけ明確にするために使用します。

WITH TABLE_COUNT AS 
(SELECT COUNT(CLIMBED.PEAK) AS NUMBER_CLIMBED, 
CLIMBER.SEX, 
CLIMBER.NAME 
FROM CLIMBED 
INNER JOIN PARTICIPATED 
ON PARTICIPATED.TRIP_ID = CLIMBED.TRIP_ID 
INNER JOIN CLIMBER 
ON CLIMBER.NAME = PARTICIPATED.NAME 
GROUP BY CLIMBER.SEX, CLIMBER.NAME; 
) 
SELECT AVG(NUMBER_CLIMBED), 
SEX 
FROM TABLE_COUNT 
GROUP BY SEX 

次に、2番目のクエリについては、私は別の方法と考えています。私はすべての登山家とテーブルを持っていて、マリアが登った各ピットのラインがあります。登ったピットマリアが登山者によって登っていない場合、列の値は1、それ以外の場合は0となります。合計がゼロの場合、登山者はマリアが上昇したすべての山を登った。

最初にマリアが登ったピットをすべて選択し、別のテーブルでピークが他の誰かに登ったら、LEFT JOINを使って参加しましょう。私はあなたがそれがどのように動作するかを知っているかどうかわかりませんが、ピークが上がらなかった場合にはNULLの値を与えます。これは私たちが探しているものです。それは、マリアが登ったピークを与えるだけで、他のピークは上昇しません。あまりにも多くの行を避けるために私はTABLE_PARTICIPERのgroup byを使っていますが、それは必要ではありません。

WITH TABLE_MARIA AS 
(
SELECT CLIMBED.PEAK 
FROM CLIMBED 
INNER JOIN PARTICIPATED 
ON PARTICIPATED.TRIP_ID = CLIMBED.TRIP_ID 
WHERE NAME IN ('MARIA') 
), 

TABLE_PARTICIPER AS 
( 
SELECT CLIMBED.PEAK, 
NAME 
FROM CLIMBED 
INNER JOIN PARTICIPATED 
ON PARTICIPATED.TRIP_ID = CLIMBED.TRIP_ID 
WHERE NAME NOT IN ('MARIA') 
GROUP BY NAME, 
CLIMBED.PEAK 
) 

今私は、彼らはそれを登った場合、彼らはしなかった場合NULL、マリア増のすべてのピーク、他のparticipersのすべての名前とピークを持つテーブルをサブクエリ、その後持つ機能とそれらを選択するウィル。

SELECT NAME 
FROM (
SELECT TABLE_MARIA.PEAK AS MARIA_PEAK, 
TABLE_PARTICIPER.PEAK AS PARTICIPER_PEAK, 
TABLE_PARTICIPER.NAME 
FROM TABLE_MARIA 
LEFT JOIN TABLE_PARTICIPER ON TABLE_MARIA.PEAK = TABLE_PARTICIPER.PEAK 
) AS QUERY 
GROUP BY NAME HAVING SUM(CASE WHEN PARTICIPER_PEAK IS NULL THEN 1 ELSE 0 END) = 0 

これは完全に機能するはずです。問題がある場合は教えてください。

最後のクエリについては、「汚れた」ものを実行できます。登山者ごとにテーブルを作って、毎日登ったピークと、それまでに参加して、各日付の各登山者の列が多くなるようにして、この日の60日前に登ったピーク数を知りましょう。その後、私たちはそれぞれのクライマーのためのカウントと行数を日付、およびだけで登山者を取ることができたためにカウントが20

WITH TABLE_PEAKS AS 
(
SELECT CLIMBED.PEAK, 
CLIMBED.WHEN, 
PARTICIPATED.NAME 
FROM CLIMBED 
INNER JOIN PARTICIPATED 
ON PARTICIPATED.TRIP_ID = CLIMBED.TRIP_ID 
) 

SELECT DISTINCT NAME 
FROM (
SELECT T1.NAME 
FROM TABLE_PEAKS T1 
LEFT JOIN TABLE_PEAKS T2 ON T1.NAME = T2.NAME AND 
(T2.WHEN > T1.WHEN OR (T2.WHEN=T1.WHEN AND T2.PEAK <>T1.PEAK)) 
AND NOT (T2.WHEN > ADDDATE(T1.WHEN,60)) 
) AS QUERY 
GROUP BY NAME 
HAVING COUNT(*) > 20 

の優れているあなたは問題がある場合を教えてください!

+0

私は最初に考え出されたものを持っていますが、2番目のクエリでは、答えをまとめて作業クエリを取得する方法がわかりません。 –

+0

Oups、申し訳ありませんが、私は2つの節の間にカンマを忘れていました。私の答えは編集されています。ごめんなさい ! – BD01

+0

私はあなたの3番目の質問のための質問がある、あなたは同じピークの3倍がある場合60日で20のピーク、または20のピークevenfを登った人々を意味するのですか?それは60日間か120日(与えられた日付の前後60日)ですか? – BD01