Using Count Average and median in SQL case when statement - count

I am trying to create a query where if the student id count is 2, then the output should be the average score of those two.
If the student id count is more than 2, then the output should be the median score of those students. I'm not getting the desired output
Here is the case-when statement that I am using:
case when (count(Student.STUDENT_ID) = 2) THEN AVG(Scores.TEST_GROWTH_PERCENTILE)
else PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY TEST_GROWTH_PERCENTILE) OVER (PARTITION BY dates.local_school_year,grade.domain_decode)
END

Related

How to average at two levels?

I am trying to average at multiple levels but am able to for one level only:
SELECT group_id,
STRFTIME("%W", date) as week_num,
AVG(count_value) as value FROM counts
GROUP BY week_num;
I get:
How to get averages for each group_id based on average of each week_num? I have to calculate average at week_num level and then average at group_id level. Expected result:
Use a subquery to calculate averages at week_num level and then calculate the average at group_id level in the outer query:
SELECT group_id, AVG(value)
FROM (
SELECT group_id,
STRFTIME("%W", date) as week_num,
AVG(count_value) as value FROM counts
GROUP BY group_id, week_num
)
GROUP BY group_id;

How to Average the most recent X entries with GROUP BY

I've looked at many answers on SO concerning situations related to this but I must not be understanding them too well as I didn't manage to get anything to work.
I have a table with the following columns:
timestamp (PK), type (STRING), val (INT)
I need to get the most recent 20 entries from each type and average the val column. I also need the COUNT() as there may be fewer than 20 rows for some of the types.
I can do the following if I want to get the average of ALL rows for each type:
SELECT type, COUNT(success), AVG(success)
FROM user_data
GROUP BY type
But I want to limit each group COUNT() to 20.
From here I tried the following:
SELECT type, (
SELECT AVG(success) AS ave
FROM (
SELECT success
FROM user_data AS ud2
WHERE umd2.timestamp = umd.timestamp
ORDER BY umd2.timestamp DESC
LIMIT 20
)
) AS ave
FROM user_data AS ud
GROUP BY type
But the returned average is not correct. The values it returns are as if the statement is only returning the average of a single row for each group (it doesn't change regardless of the LIMIT).
Using sqlite, you may consider the row_number function in a subquery to acquire/filter the most recent entries before determining the average and count.
SELECT
type,
AVG(val),
COUNT(1)
FROM (
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY type
ORDER BY timestamp DESC
) rn
FROM
user_data
) t
WHERE rn <=20
GROUP BY type

How to get the proportion of values in a column >X?

Using sqlite3, I have a column "grades" in table "students" and I want to get the proportion of students who scored over 80 on a test. How do I get that? I can select count(*) from students and then select count(*) from students where score>80, but how do I get the proportion in one statement?
Here is a simple way to do this:
SELECT
AVG(CASE WHEN grades > 80 THEN 1 ELSE 0 END)
FROM students;
This just takes a conditional average over the entire table, counting the number of students with a grade over 80, then normalizing that count by the total number of students.

sqlite syntax error with hex function

I wanted to select the 1st row of the table X below and update the column "name" to '53656C696E613333' as shown below. Sqlite keeps saying syntax error. Can someone please assist with this problem? Many thanks!
CREATE TABLE Ages (name VARCHAR(128),age INTEGER)`
DELETE FROM Ages;
INSERT INTO Ages (name,age) Values ('Alex',25);
INSERT INTO Ages (name,age) Values ('Mel',31);
INSERT INTO Ages (name,age) Values ('Fred',30);
INSERT INTO Ages (name,age) Values ('Nancy',35);
INSERT INTO Ages (name,age) Values ('Nathan',13);
INSERT INTO Ages (name,age) Values ('Oscar',24);
SELECT hex (name||age) AS X FROM Ages ORDER BY X
SELECT * FROM X LIMIT 1
UPDATE X SET name = '53656C696E613333'
I think you might be wanting something like :-
UPDATE Ages
SET name = '53656C696E613333'
WHERE name = (SELECT name FROM Ages ORDER BY hex(name||age) LIMIT(1))
AND age = (SELECT age FROM Ages ORDER BY hex(name||age) LIMIT(1))
;
as a replacement for :-
SELECT hex (name||age) AS X FROM Ages ORDER BY X
SELECT * FROM X LIMIT 1
UPDATE X SET name = '53656C696E613333'
This would result in :-
However, as you haven't specified WITHOUT ROWID for the table, then you could use the simpler :-
UPDATE Ages
SET name = '53656C696E613333'
WHERE rowid = (SELECT rowid FROM Ages ORDER BY hex(name||age) LIMIT(1))
;

Selecting multiple maximum values? In Sqlite?

Super new to SQLite but I thought it can't hurt to ask.
I have something like the following table (Not allowed to post images yet) pulling data from multiple tables to calculate the TotalScore:
Name TotalScore
Course1 15
Course1 12
Course2 9
Course2 10
How the heck do I SELECT only the max value for each course? I've managed use
ORDER BY TotalScore LIMIT 2
But I may end up with multiple Courses in my final product, so LIMIT 2 etc won't really help me.
Thoughts? Happy to put up the rest of my query if it helps?
You can GROUP the resultset by Name and then use the aggregate function MAX():
SELECT Name, max(TotalScore)
FROM my_table
GROUP BY Name
You will get one row for each distinct course, with the name in column 1 and the maximum TotalScore for this course in column 2.
Further hints
You can only SELECT columns that are either grouped by (Name) or wrapped in aggregate functions (max(TotalScore)). If you need another column (e.g. Description) in the resultset, you can group by more than one column:
...
GROUP BY Name, Description
To filter the resulting rows further, you need to use HAVING instead of WHERE:
SELECT Name, max(TotalScore)
FROM my_table
-- WHERE clause would be here
GROUP BY Name
HAVING max(TotalScore) > 5
WHERE filters the raw table rows, HAVING filters the resulting grouped rows.
Functions like max and sum are "aggregate functions" meaning they aggregate multiple rows together. Normally they aggregate them into one value, like max(totalscore) but you can aggregate them into multiple values with group by. group by says how to group the rows together into aggregates.
select name, max(totalscore)
from scores
group by name;
This groups all the columns together with the same name and then does a max(totalscore) for each name.
sqlite> select name, max(totalscore) from scores group by name;
Course1|15
Course2|12

Resources