我的数据库看起来像这样:
PEAK(NAME,ELEV,DIFF,MAP,REGION)
CLIMBER(NAME,SEX)
参与(TRIP_ID,NAME)
CLIMBED(TRIP_ID,PEAK,WHEN)
我需要帮助w /为这两个示例场景编写SQL查询:
编辑:第一个查询现在有效,如下所示:
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;
这个查询给了我攀爬我的男性和女性的峰值总数。但我似乎无法弄清楚如何获得平均数而不是数量。我知道你不能简单地将COUNT函数更改为AVG b / c我的数据是字符串形式而不是整数。
我的第二个查询如下:
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;
这个查询给出了所有登山者的名字以及他们每次登山时的峰值总数,但我不知道如何过滤它们,以便它只显示那些已经攀登20多个峰值的人一天的跨度。 我尝试使用
HAVING CLIMBED.WHEN BETWEEN -60 AND 60;
但这不起作用。
非常感谢任何帮助,我使用Oracle Express作为我的数据库。
答案 0 :(得分: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
然后,关于你的第二个问题,我会以另一种方式思考。每个登山者都有一张桌子,玛丽亚攀爬的每个坑都有一条线。如果登山者没有爬过玛丽亚攀登的坑,那么一列将以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
如果他们没有,然后选择具有函数的那个。< / p>
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
告诉我你是否有问题!