我的数据库看起来像这样:
PEAK提供有关用户感兴趣的山峰的信息。该表列出了每个峰的名称,高程(以英尺为单位),其难度级别(以1-5为单位),其中的地图位于内华达山脉及其所在地区。
CLIMBER列出了俱乐部的成员,并列出了他们的姓名和性别。
PARTICIPATED为参加各种攀岩之旅的登山者提供了一套。每次旅行的参与者人数各不相同。
CLIMBED告诉我们每次登山旅行时攀爬的峰值,以及每个峰值爬升的数据。
我需要帮助编写以下内容的查询:
对于第一个查询,到目前为止,我已经找到了一种方法来计算男性所攀升的峰值总数:
SELECT SUM(C)
FROM
(SELECT CD.PEAK, COUNT(*) C
FROM CLIMBED CD
WHERE CD.TRIP_ID IN
(SELECT TRIP_ID
FROM PARTICIPATED PA
WHERE PA.NAME IN
(SELECT NAME
FROM CLIMBER
WHERE SEX = 'M'))
GROUP BY CD.PEAK) T;
对于第二个查询,我有以下内容,我相当肯定是不正确的:
SELECT TEMP2.TRIP_ID, COUNT (*)
FROM
(SELECT P1.NAME, P2.NAME, P1.TRIP_ID
FROM PARTICIPATED P1, PARTICIPATED P2
WHERE P1.NAME <> P2.NAME AND
P1.TRIP_ID = P2.TRIP_ID) TEMP1,
(SELECT *
FROM CLIMBED) TEMP2
WHERE TEMP2.TRIP_ID = TEMP1.TRIP_ID
GROUP BY TEMP2.TRIP_ID;
答案 0 :(得分:0)
问题1: 总行程次数(包括每次攀登高峰时)
SELECT t1.sex, AVG(t1.peak_count) AS average
FROM
(SELECT sex, COUNT(trip_id) AS peak_count
FROM climber c LEFT JOIN participated p ON c.name = p.name GROUP BY c.name, c.sex) t1
每次爬上一个独特的高峰时:
SELECT t1.sex, AVG(t1.peak_count) AS average
FROM
(SELECT sex, COUNT(trip_id) AS peak_count
FROM climber c LEFT JOIN participated p ON c.name = p.name GROUP BY c.name, c.sex) t1
问题2:
SELECT P1.Name, P2.Name, COUNT(DISTINCT p1.trip_id) AS trips
FROM participated p1 INNER JOIN participated p2 ON p1.trip_id = p2.trip_id
WHERE p1.name > p2.name -- > instead of <> gets only one of the pairs
GROUP BY P1.Name, P2.Name
HAVING COUNT(DISTINCT p1.trip_id) > 0
ORDER BY trips DESC
问题3:
SELECT p.name, cl.when AS span_begin_date, DATEADD(day, 60, cl.when) AS span_end_date, count(c2.trip_id) AS peaks
FROM climbed cl LEFT JOIN
climbed c2 ON c2.when BETWEEN cl.when AND DATEADD(day, 60, cl.when)
GROUP BY p.name, cl.when, DATEADD(day, 60, cl.when)
HAVING COUNT(c2.trip_id) > 20
ORDER BY peaks
答案 1 :(得分:0)
这是我的解决方案。如果您提供样本数据,则可以验证。对于问题3,大约60天的时间跨度尚不清楚。你能指点一下吗?
问题1
select x.sex, avg(x.peaks_escalated) as peaks
from (
select u.name, u.sex, count(distinct c.peak) as peaks_escalated
from t1_climbed c
inner join t1_participated p on c.trip_id = p.trip_id
inner join t1_climber u on p.name = u.name
group by u.name, u.sex ) x
group by x.sex
问题2
with list1 as (
select u.name as member, c.trip_id, c.peak, c.when
from t1_climbed c
inner join t1_participated p on c.trip_id = p.trip_id
inner join t1_climber u on p.name = u.name
)
select a.member as m1, b.member as m2, count(distinct a.peak) as total
from list1 a inner join list1 b
on a.trip_id = b.trip_id
and a.peak = b.peak
and a.when = b.when
and a.member <> b.member
group by a.member, b.member
答案 2 :(得分:0)
Oracle安装程序:
CREATE TABLE PEAK (
NAME VARCHAR2(50) PRIMARY KEY,
ELEV INT,
DIFF INT,
MAP VARCHAR2(10),
REGION VARCHAR2(10)
);
CREATE TABLE CLIMBER (
NAME VARCHAR2(50) PRIMARY KEY,
SEX CHAR(1) CHECK ( SEX IN ( 'M', 'F' ) )
);
-- Created this to have a primary key
CREATE TABLE TRIPS (
TRIP_ID INT PRIMARY KEY
);
CREATE TABLE PARTICIPATED (
TRIP_ID INT REFERENCES TRIPS( TRIP_ID ),
NAME VARCHAR2(50) REFERENCES CLIMBER( NAME ),
PRIMARY KEY ( TRIP_ID, NAME )
);
CREATE TABLE CLIMBED (
TRIP_ID INT REFERENCES TRIPS( TRIP_ID ),
PEAK VARCHAR2(50) REFERENCES PEAK ( NAME ),
"WHEN" DATE
);
问题1
SELECT sex,
AVG( num_peaks ) AS avg_peaks
FROM (
SELECT c.*,
COUNT( DISTINCT l.peak ) num_peaks
FROM CLIMBED l
INNER JOIN
PARTICIPATED p
ON ( p.trip_id = l.trip_id )
RIGHT OUTER JOIN
CLIMBER c
ON ( p.name = c.name )
GROUP BY c.name, c.sex
)
GROUP BY sex;
你需要OUTER JOIN
登山者,因为他们可能没有参加任何旅行(因此攀登了0个峰值),这需要在平均值中加以考虑。一个人也有可能多次攀登过一个峰值 - 当你想要在同一个峰值上排除多个攀爬的人攀登的峰值数量时,需要使用COUNT( DISTINCT ... )
(或其他类似物)技术) - 如果你想计算多次爬升,那么删除DISTINCT
关键字。
问题2 :
SELECT *
FROM (
SELECT name1,
name2,
COUNT( DISTINCT c.peak ) AS num_peaks_climbed
FROM (
SELECT p1.name AS name1,
p2.name AS name2,
p1.trip_id
FROM PARTICIPATED p1
INNER JOIN
PARTICIPATED p2
ON ( p1.trip_id = p2.trip_id AND p1.name < p2.name )
) p
INNER JOIN
climbed c
ON ( p.trip_id = c.trip_id )
GROUP BY name1, name2
ORDER BY num_peaks_climbed DESC
)
WHERE ROWNUM = 1;
问题3 :
SELECT *
FROM (
SELECT p.name,
COUNT( c.peak ) OVER ( PARTITION BY p.name
ORDER BY c."WHEN"
RANGE BETWEEN INTERVAL '-60' DAY PRECEDING
AND CURRENT ROW
) AS num_peaks_in_60_days,
c."WHEN" AS last_date_of_range
FROM PARTICIPATED p
INNER JOIN
climbed c
ON ( p.trip_id = c.trip_id )
)
WHERE num_peaks_in_60_days > 20;