hi i need help combining 2 cte to get who get 100 attendance percentage but failed at exam
here my first cte
with main as(
select ca.STUDENT_ID,
ca.SCHEDULE_ID,
s.COURSE_ID,
co.NAME as course_name,
st.NAME,
count(ca.ID) as total_attendance,
((CHAR_LENGTH(s.COURSE_DAYS) - CHAR_LENGTH(REPLACE(s.COURSE_DAYS , ',', '')) + 1) * 13) as attendance_needed
from univ.course_attendance ca
left join univ.schedule s on ca.SCHEDULE_ID = s.ID
left join univ.student st on ca.SCHEDULE_ID = st.ID
left join univ.course co on ca.SCHEDULE_ID = co.ID
group by ca.STUDENT_ID, ca.SCHEDULE_ID
)
select *,total_attendance/attendance_needed as attendance_percentage
from main
order by 1,2;
second cte
;with inputdata as
(
select es.STUDENT_ID,es.EXAM_ID,es.SCORE,e.PASS_THRESHOLD, s.NAME , c.NAME as Course_name, es.EXAM_DT,
case
when SCORE>=PASS_THRESHOLD then 'PASS'
else 'Fail'
end as Flag
from exam_submission es
left join student s on es.STUDENT_ID = s.ID
left join exam e on es.EXAM_ID = e.ID
left join course c on e.COURSE_ID = c.ID
)
select * from inputdata I
join
( select student_id,exam_id from
inputdata
group by student_id, exam_id
)T on I.student_id=T.student_id and I.exam_id=T.exam_id
order by exam_dt asc
result:
what i need student name, course name, attendace percentage & flag "failed/pass"
Just chain multiple table expressions in a single CTE by introducing "aliases" like main_ordered for the first CTE and inputdata_grouped for the second one. I'm sticking with the original naming, but it could be improved.
with
main as (
select ca.STUDENT_ID,
...
group by ca.STUDENT_ID, ca.SCHEDULE_ID),
main_ordered as (
select *,total_attendance/attendance_needed as attendance_percentage
...
order by 1,2),
inputdata as (
select es.STUDENT_ID,es.EXAM_ID,es.S...
...),
inputdata_grouped as (
select * from inputdata I
...
group by student_id, exam_id...
...
order by exam_dt asc)
select *
from main_ordered join inputdata_grouped on ...
Related
-- Note: The actor should have acted in at least five Indian movies. -- (Hint: You should use the weighted average based on votes. If the ratings clash, then the total number of votes should act as the tie breaker
SELECT n.name as actor_name
, r.total_votes
, COUNT(r.movie_id) as movie_count
, r.avg_rating as actor_avg_rating
, RANK() OVER( PARTITION BY
rm.category = 'actor'
ORDER BY
r.avg_rating DESC
) actor_rank
FROM names as n
JOIN role_mapping as rm
ON n.id = rm.movie_id
JOIN movie as m
ON m.id = rm.movie_id
JOIN ratings as r
ON r.movie_id = m.id
where m.country regexp '^INDIA$'
and m.languages regexp '^HINDI$'
group
by actor_name
having count(rm.movie_id) >= 5;
The output gives no error but no result too.
This would work:
SELECT a.name as actor_name, c.total_votes, COUNT(c.movie_id) as movie_count,c.avg_rating as actor_avg_rating,
RANK() OVER( PARTITION BY
d.category = 'actor'
ORDER BY
c.avg_rating DESC
) actor_rank
FROM names a, movie b, ratings c, role_mapping d
where b.country = 'INDIA'
and b.id = c.movie_id
and b.id= d.movie_id
and a.id = d.name_id
group by actor_name
having count(d.movie_id) >= 5
order by actor_avg_rating desc
;
You had tried joining nameid with movie id which is the mistake
SELECT NAME AS actor_name,
Cast(Sum(total_votes)/Count(movie_id) AS DECIMAL(8,0)) AS total_votes,
Count(movie_id) AS movie_count,
avg_rating AS actor_avg_rating,
Dense_rank() OVER(ORDER BY avg_rating DESC) AS actor_rank
FROM names n INNER JOIN role_mapping r ON n.id=r.name_id
INNER JOIN ratings using (movie_id) INNER JOIN movie m ON m.id=r.movie_id
WHERE country="india" AND category="actor"
GROUP BY actor_name
HAVING Count(movie_id)>=5;
WITH top_actor
AS (SELECT b.NAME
AS
actor_name,
Sum(c.total_votes)
AS
total_votes,
Count(DISTINCT a.movie_id)
AS
movie_count,
Round(Sum(c.avg_rating * c.total_votes) / Sum(c.total_votes), 2)
AS
actor_avg_rating
FROM role_mapping a
INNER JOIN names b
ON a.name_id = b.id
INNER JOIN ratings c
ON a.movie_id = c.movie_id
INNER JOIN movie d
ON a.movie_id = d.id
WHERE a.category = 'actor'
AND d.country LIKE '%India%'
GROUP BY a.name_id,
b.NAME
HAVING Count(DISTINCT a.movie_id) >= 5)
SELECT *,
Rank()
OVER (
ORDER BY actor_avg_rating DESC) AS actor_rank
FROM top_actor;
I'm using the following query to sort, using Order by for 4 different ranks: id, avg_rating, total_sent & points
However, I'm having trouble with including all the members in the results. I'd like to include all members, including the ones that have 0: total_sent, total_received, points, avg_rating, votes
Please help me understand what I'm missing. Thank you.
SELECT m.id,
m.Name,
m.City,
m.Zip_Code,
m.url,
r.avg_rating,
r.votes,
froms.from_ct total_sent,
tos.to_ct total_received,
froms.from_ct - tos.to_ct `points`
FROM members m
JOIN (
SELECT id_rated,
avg(rating) avg_rating,
count(*) votes
FROM member_ratings
GROUP BY id_rated
) r ON r.id_rated = m.id
JOIN ( SELECT id_from, COUNT(*) AS from_ct FROM member_points GROUP BY 1
) AS froms ON froms.id_from = m.id
JOIN ( SELECT id_received, COUNT(*) AS to_ct FROM member_points GROUP BY 1
) AS tos ON tos.id_received = m.id
WHERE m.Account_Active = 'TRUE'
GROUP BY m.id,
m.Name
ORDER BY `avg_rating` DESC;
Use LEFT JOINs for all tables
SELECT m.id,
m.Name,
m.City,
m.Zip_Code,
m.url,
r.avg_rating,
r.votes,
froms.from_ct total_sent,
tos.to_ct total_received,
froms.from_ct - tos.to_ct `points`
FROM members m
LEFT JOIN (
SELECT id_rated,
avg(rating) avg_rating,
count(*) votes
FROM member_ratings
GROUP BY id_rated
) r ON r.id_rated = m.id
LEFT JOIN ( SELECT id_from, COUNT(*) AS from_ct FROM member_points GROUP BY 1
) AS froms ON froms.id_from = m.id
LEFT JOIN ( SELECT id_received, COUNT(*) AS to_ct FROM member_points GROUP BY 1
) AS tos ON tos.id_received = m.id
LEFT JOIN member_points mp ON mp.id_points = m.id
WHERE m.Account_Active = 'TRUE'
GROUP BY m.id,
m.Name
ORDER BY `avg_rating` DESC;
I have three tables:
customers: id, name
contracts_jewels: id, customer_id, paid, transferred, final_date
contracts_objects: id, customer_id, paid, transferred, final_date
As you see, the structure of the last two tables is the same.
The "paid" and the "transferred" fields contain the value 0 or 1.
What I need is to make a query which should return all the clients (no matter if they have contracts or not), and for each client:
id, name, count_contracts_all, count_contracts_active
where:
count_contracts_all would mean the sum of [SELECT COUNT( * ) FROM
contracts_jewels WHERE customer_id=3 (for example)] and [SELECT
COUNT( * ) FROM contracts_objects WHERE customer_id=3 (for example)]
count_contracts_active would mean the sum of [SELECT COUNT( * ) FROM
contracts_jewels WHERE customer_id=3 AND final_date>=Now() AND paid=0
AND transferred=0] and [SELECT COUNT( * ) FROM contracts_objects WHERE
customer_id=3 AND final_date>=Now() AND paid=0 AND transferred=0]
Any idea? Would you please help me? Thank you!
You can count the contracts separately and then just join them up to the customers:
SELECT
c.id,
COALESCE(oc.active_count,0) + COALESCE(jc.active_count,0) as count_contracts_active,
COALESCE(oc.total_count,0) + COALESCE(jc.total_count,0) as count_contracts_all
FROM customers c
LEFT JOIN (
SELECT
customer_id
COUNT(*) as total_count,
COUNT(IF(final_date>=Now() AND paid=0 AND transferred=0,1,NULL)) as active_count
FROM contracts_jewels
GROUP BY customer_id
) as oc ON oc.customer_id = c.id
LEFT JOIN (
SELECT
customer_id
COUNT(*) as total_count,
COUNT(IF(final_date>=Now() AND paid=0 AND transferred=0,1,NULL)) as active_count
FROM contracts_objects
GROUP BY customer_id
) as jc ON jc.customer_id = c.id
One fast solution I can think of right now is:
SELECT COUNT(`temp_table`.*) FROM (
SELECT * FROM contracts_jewels WHERE customer_id=3 UNION ALL
SELECT * FROM contracts_objects WHERE customer_id=3) AS `temp_table`
AND
SELECT COUNT(`temp_table`.*) FROM (
SELECT * FROM contracts_jewels WHERE customer_id=3 AND final_date>=Now() AND paid=0 AND transferred=0 UNION ALL
SELECT * FROM contracts_objects WHERE customer_id=3 AND final_date>=Now() AND paid=0 AND transferred=0) AS `temp_table`
You can join each of those tables twice and add their corresponding COUNTs in your result:
SELECT
c.id,
(COUNT(cj1.id)+COUNT(co1.id)) AS count_contracts_all,
(COUNT(cj2.id)+COUNT(co2.id)) AS count_contracts_active
FROM
customers c
LEFT OUTER JOIN contracts_jewels cj1 ON c.id = cj1.customer_id
LEFT OUTER JOIN contracts_objects co1 ON c.id = co1.customer_id
LEFT OUTER JOIN contracts_jewels cj2 ON
c.id = cj2.id AND
cj2.final_date >= NOW() AND
cj2.paid = 0 AND
cj2.transferred = 0
LEFT OUTER JOIN contracts_object co2 ON
c.id = co2.id AND
co2.final_date >= NOW() AND
co2.paid = 0 AND
co2.transferred = 0
GROUP BY c.id
Note: I haven't run this, but hopefully it sets you in the right direction.
simple solution:
SELECT SUM(c) FROM (
SELECT COUNT(1) as c FROM `tbl1` where ...
UNION
SELECT COUNT(1) as c FROM tbl2 where ...
UNION
SELECT COUNT(1) as c FROM tbl3 where ...
) al
I am tying to ordering a sub query before grouping it. The problem is that the sub query is order as if we take it just like a query. But as sub query order by does nothing.
Here's the query:
SELECT * FROM (
SELECT
a.id,
citypair,
a.season,
airline,
class,
fare,
rbd,
season_from,
season_to,
schedule_id,
cp.departure_id,
cp.destination_id,
sch.date_time
FROM tarifftool_price_log as a
JOIN tarifftool_seasons as b ON a.seasonId = b.id
JOIN tarifftool_citypairs as cp ON citypair = cp.id
JOIN tarifftool_schedule_queue AS sch ON schedule_id = sch.id
WHERE b.date = '12/26' AND class = 'b' ORDER BY schedule_id DESC) as qq
GROUP BY citypair, airline
Now i'am just trying as a result get a ordered query. If I do achieve this, i will have no problem grouping my data.
Use Row_Number in sub query
ROW_NUMBER() OVER(ORDER BY schedule_id)
SELECT * FROM (
SELECT
ROW_NUMBER() OVER(ORDER BY schedule_id DESC ) as RowId,
a.id,
citypair,
a.season,
airline,
class,
fare,
rbd,
season_from,
season_to,
schedule_id,
cp.departure_id,
cp.destination_id,
sch.date_time
FROM tarifftool_price_log as a
JOIN tarifftool_seasons as b ON a.seasonId = b.id
JOIN tarifftool_citypairs as cp ON citypair = cp.id
JOIN tarifftool_schedule_queue AS sch ON schedule_id = sch.id
WHERE b.date = '12/26' AND class = 'b' ) as qq
GROUP BY citypair, airline
http://sqlfiddle.com/#!2/37dd94/17
If I do SELECT DISTINCT I get the same results as doing just SELECT.
On the query results, you will see two activities that contains the District "Evora".
Only one should appear.
Any clue?
How about the following query (SQL FIDDLE):
SELECT GROUP_CONCAT(APA_T.district), t.name
FROM tbl_activity AS t
JOIN tbl_activity_package AS ap ON t.id = ap.id_activity
JOIN
(
SELECT DISTINCT apa.district AS district,
(
SELECT s1.id_activity_package
FROM tbl_activity_package_address s1
WHERE apa.district = s1.district
ORDER BY s1.id DESC
LIMIT 1
) AS idActivityPackage
FROM
tbl_activity_package_address apa
ORDER BY apa.district
) AS APA_T
ON ap.id = APA_T.idActivityPackage
GROUP BY t.name
ORDER BY APA_T.district;
The above query will eliminate the extra Faro and Evora.