简体   繁体   中英

How to combine these two sql statements

I am not very experienced in sql but can generally get by in structuring basic queries, but this is too complex for me to work out.

I have two queries which each give the results I need individually, however I need to combine them to get the final result I need.

In one query it grabs all "scores" for a particular student and returns an average. In the other query I strip the highest and lowest records from the table.

I want to combine these queries to first strip the highest and lowest scores, then to return the average score from ONLY the remaining records. Please help guide me to the correct syntax to use.

my queries:


This returns ALL the highest and lowest scores:

SELECT *
FROM `scores`
WHERE `tot_score` = (
SELECT MAX( `tot_score` )
FROM `scores` )
OR `tot_score` = (
SELECT MIN( `tot_score` )
FROM `scores` ) 

This returns the average scores:

SELECT `pres_id`, COUNT( `pres_id` ) , ROUND( AVG( `tot_score` ) , 2 ) , `username`, `name`, `pres_day`
FROM `scores`, `users`
WHERE `users.id_user` = `scores.pres_id`
GROUP BY `pres_id`

How can I combine these to get the result I need?

I would suggest that you do the calculation of the min and max values in a single subquery. Then you can simply take the rows that you want using a where clause to filter:

SELECT s.`pres_id`, COUNT( `pres_id` ), ROUND( AVG( `tot_score` ) , 2 ) ,
       `username`, `name`, `pres_day`
FROM `scores` s join
     `users` u
     on u.id_user = s.pres_id join
     (select s.pres_id, max(tot_score) as maxts, min(tot_score) as mints
      from scores s
      group by s.pres_id
     ) ssum
     on u.id_user = ssum.pres_id
where s.tot_score > ssum.mints and s.tot_score < ssum.maxts
GROUP BY s.`pres_id`;

I am guessing that you want to strip the highest and lowest scores for each student. If you just want to omit the highest and lowest for all students, then use the following:

SELECT s.`pres_id`, COUNT( `pres_id` ), ROUND( AVG( `tot_score` ) , 2 ) ,
       `username`, `name`, `pres_day`
FROM `scores` s join
     `users` u
     on u.id_user = s.pres_id cross join
     (select max(tot_score) as maxts, min(tot_score) as mints
      from scores s
     ) ssum
where s.tot_score > ssum.mints and s.tot_score < ssum.maxts
GROUP BY s.`pres_id`;

EDIT:

Modification to keep score when there is only one score for a student:

SELECT s.`pres_id`, COUNT( `pres_id` ), ROUND( AVG( `tot_score` ) , 2 ) ,
       `username`, `name`, `pres_day`
FROM `scores` s join
     `users` u
     on u.id_user = s.pres_id join
     (select s.pres_id, max(tot_score) as maxts, min(tot_score) as mints,
             count(*) as cnt
      from scores s
      group by s.pres_id
     ) ssum
     on u.id_user = ssum.pres_id
where (s.tot_score > ssum.mints and s.tot_score < ssum.maxts) or (cnt = 1)
GROUP BY s.`pres_id`;

You should be able to invert the high/low scores query and then use it as a result set in the existing average query:

SELECT `pres_id`, COUNT( `pres_id` ) , ROUND( AVG( `tot_score` ) , 2 ) , `username`, `name`, `pres_day`
FROM (
    SELECT `tot_score`
    FROM `scores`
    WHERE `tot_score` <> (
    SELECT MAX( `tot_score` )
    FROM `scores` )
    OR `tot_score` <> (
    SELECT MIN( `tot_score` )
    FROM `scores` ) 
) AS `scores`, `users`
WHERE `users.id_user` = `scores.pres_id`
GROUP BY `pres_id`

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM