with connection.cursor() as cursor: cursor.execute( f""" SELECT CAST( ROUND( (SELECT COUNT(*) FROM uinterview_delivery -- 需*100.0,否則會被當成int WHERE uinterview_delivery.delivery_date = uinterview_delivery.order_date) * 100.0 / COUNT(*) , 2) AS double precision) AS real_time_order_percent FROM uinterview_delivery """ )
with connection.cursor() as cursor: cursor.execute( f""" UPDATE uinterview_email SET is_delete = true WHERE NOT (id IN ( SELECT DISTINCT ON (email) id FROM uinterview_email ORDER BY email ASC, id ASC) ) RETURNING *; """ )
==================== Employee Table ==================== id name sex sex2 ---- ------ ----- ------ 109 John M 110 Dan F 111 Brad M 112 Tomas F =============== Employee Bonus Table =============== id employee bonus ---- ---------- ------- 55 110 500 56 112 2000
with connection.cursor() as cursor: cursor.execute( f""" SELECT U0.id, U0.name, U0.sex, COALESCE( (SELECT SUM(U2.bonus) FROM uinterview_employeebonus U2 WHERE U2.employee_id = U0.id), 0) AS bonus FROM uinterview_employee U0 WHERE NOT (U0.id IN ( SELECT U1.employee_id FROM uinterview_employeebonus U1 WHERE U1.bonus >= 750)) ORDER BY bonus, U0.name """ )
utils.print_cursor(cursor)
# Print result: # id name sex bonus # ---- ------ ----- ------- # 111 Brad M 0 # 109 John M 0 # 110 Dan F 500
==================== Employee Table ==================== id name sex sex2 ---- ------ ----- ------ 109 John M 110 Dan F 111 Brad M 112 Tomas F
Answer
1 2 3 4 5 6 7 8 9
sex2為題目答案。 ==================== Employee Table ==================== id name sex sex2 ---- ------ ----- ------ 109 John M F 110 Dan F M 111 Brad M F 112 Tomas F M
# 透過CASE WHEN THEN END更新sex2 Employee.objects.all().update( sex2=Case(When(sex='M', then=Value('F')), default=Value('M')) )
utils.print_queryset(Employee.objects.all())
# Print result: # ==================== Employee Table ==================== # id name sex sex2 # ---- ------ ----- ------ # 109 John M F # 110 Dan F M # 111 Brad M F # 112 Tomas F M
with connection.cursor() as cursor: cursor.execute( f""" UPDATE uinterview_employee SET sex2 = CASE WHEN (sex = 'M') THEN 'F' ELSE 'M' END RETURNING *; """ )
utils.print_cursor(cursor)
# Print result: # id name sex sex2 # ---- ------ ----- ------ # 109 John M F # 110 Dan F M # 111 Brad M F # 112 Tomas F M
with connection.cursor() as cursor: cursor.execute( f""" SELECT id, name, available_date, (SELECT COALESCE(Sum(U1.qty), 0) FROM uinterview_order U1 WHERE (U1.product_id = U0.id AND dispatch_date >= '2018-06-23T00:00:00'::timestamp)) AS total_of_qty FROM uinterview_product U0 WHERE ((SELECT COALESCE(Sum(U2.qty), 0) FROM uinterview_order U2 WHERE (U2.product_id = U0.id AND U2.dispatch_date >= '2018-06-23T00:00:00'::timestamp)) < 10 AND U0.available_date >= '2019-05-24T00:00:00'::timestamp) """ )
utils.print_cursor(cursor)
# Print result: # id name available_date total_of_qty # ---- -------- ------------------- -------------- # 3 Product3 2019-06-10 00:00:00 1
題目六
Question
找出表格中所有部門的學生人數,並按學生人數由大到小、部門名稱由小到大排序。
1 2 3 4 5 6 7 8 9 10 11 12
========== Department Table ========== id name ---- ----------- 1 Engineering 2 Science 3 Law ==================== Student Table ==================== id department name gender ---- ------------ ------ -------- 1 1 Jack M 2 1 Jan F 3 2 Mark M
Answer
1 2 3 4 5
id name total_of_students ---- ----------- ------------------- 1 Engineering 2 2 Science 1 3 Law 0
with connection.cursor() as cursor: cursor.execute( f""" SELECT id, name, (SELECT COALESCE(Count(*), 0) FROM uinterview_student U1 WHERE U1.department_id = U0.id) AS total_of_students FROM uinterview_department U0 ORDER BY total_of_students DESC, name ASC; """ )
utils.print_cursor(cursor)
# Print result: # id name total_of_students # ---- ----------- ------------------- # 1 Engineering 2 # 2 Science 1 # 3 Law 0
with connection.cursor() as cursor: cursor.execute( f""" -- 透過GROUP BY user_id後在進行COUNT(*),可以得到每個user的評論次數 SELECT * FROM (SELECT user_id, (SELECT name FROM uinterview_user WHERE id = user_id) AS user_name, COUNT(*) AS total_of_comment FROM uinterview_movierating GROUP BY user_id ORDER BY total_of_comment DESC, user_name ASC) U0 -- 只顯示最多評論次數的用戶 WHERE total_of_comment = ( SELECT MAX(total_of_comment) FROM (SELECT user_id,COUNT(*) AS total_of_comment FROM uinterview_movierating GROUP BY user_id) U1 ) """ )
with connection.cursor() as cursor: cursor.execute( f""" -- 透過GROUP BY movie_id後在進行SUM(rating),可以得到每個movie的評分總和 SELECT * FROM (SELECT movie_id, (SELECT name FROM uinterview_movie WHERE id = movie_id) AS movie_name, SUM(rating) AS total_of_rating FROM uinterview_movierating WHERE create_date BETWEEN '2020-02-01' AND '2020-02-29' GROUP BY movie_id ORDER BY total_of_rating DESC, movie_name ASC) U0 -- 只顯示最高評分電影 WHERE total_of_rating = ( SELECT MAX(total_of_rating) FROM (SELECT movie_id, SUM(rating) AS total_of_rating FROM uinterview_movierating WHERE create_date BETWEEN '2020-02-01' AND '2020-02-29' GROUP BY movie_id) U1 ) """ )
consecutive_login_days = 4 with connection.cursor() as cursor: cursor.execute( f""" SELECT account_id, (SELECT name FROM uinterview_account WHERE id = account_id) AS name, CONCAT(count(sub_date),'天') AS login_days, first_login_at FROM ( SELECT account_id, group_seq, TO_CHAR(login_date,'YYYY-mm-dd') AS login_date, TO_CHAR(sub_date,'YYYY-mm-dd') AS sub_date, TO_CHAR( CASE WHEN group_seq = 1 THEN login_date WHEN sub_date = LAG(sub_date,1) OVER(PARTITION BY account_id ORDER BY login_date) THEN LAG(login_date,CAST(group_seq AS INT)-1) OVER() ELSE login_date END ,'YYYY-mm-dd') AS first_login_at FROM ( -- 如有連續相同sub_date代表是連續登入日期 -- 例如: -- login_date(2022-01-02) - group_seq(1) = 2022-01-01 -- login_date(2022-01-03) - group_seq(2) = 2022-01-01 -- login_date(2022-01-04) - group_seq(3) = 2022-01-01 -- login_date(2022-01-10) - group_seq(4) = 2022-01-06 SELECT *, login_date - (group_seq || 'DAY')::INTERVAL AS sub_date FROM( -- 以group_seq來分組,後續login_date - group_seq天來判斷是否為連續登入 SELECT *, ROW_NUMBER() OVER(PARTITION BY account_id ORDER BY login_date) AS group_seq FROM ( -- 過濾掉同一天多次登入日期,只保留一筆資料 SELECT DISTINCT account_id ,login_date FROM uinterview_accountlogin ORDER BY login_date ) U0 ) U1 ) U2 ) U3 GROUP BY account_id,sub_date,first_login_at HAVING count(*) >= {consecutive_login_days} ORDER BY account_id,first_login_at; """ )
utils.print_cursor(cursor)
# Print result: # account_id name login_days first_login_at # ------------ -------- ------------ ---------------- # 7 Jonathan 5天 2020-05-30