select d.Name as Department, a. Nameas Employee, a. Salary from ( select e.*, dense_rank() over (partitionby DepartmentId orderby Salary desc) as DeptPayRank from Employee e ) a join Department d on a.DepartmentId = d.Id where DeptPayRank <=3;
SELECT E1.salary FROM Employee AS E1 WHERE3 > ( SELECTCOUNT(DISTINCT E2.Salary) FROM Employee AS E2 WHERE E1.Salary < E2.Salary AND E1.DepartmentId = E2.DepartmentId );
SELECT D.Name AS Department, E1.Name AS Employee, E1.Salary AS Salary FROM Employee AS E1 LEFTJOIN Department AS D ON E1.departmentId = D.Id WHERE3 > ( SELECTCOUNT(DISTINCT E2.Salary) FROM Employee AS E2 WHERE E1.Salary < E2.Salary AND E1.DepartmentId = E2.departmentId ) ORDERBY Department, Salary DESC;
# Write your MySQL query statement below SELECT D.Name AS Department, E1.Name AS Employee, E1.Salary AS Salary FROM Employee AS E1 INNERJOIN Department AS D ON E1.departmentId = D.Id WHERE3 > ( SELECTCOUNT(DISTINCT E2.Salary) FROM Employee AS E2 WHERE E1.Salary < E2.Salary AND E1.DepartmentId = E2.departmentId ) ORDERBY Department, Salary DESC;
The Employee table holds all employees. The employee table has three columns: Employee Id, Company Name, and Salary. +-----+------------+--------+ |Id | Company | Salary | +-----+------------+--------+ |1 | A | 2341 | |2 | A | 341 | |3 | A | 15 | |4 | A | 15314 | |5 | A | 451 | |6 | A | 513 | |7 | B | 15 | |8 | B | 13 | |9 | B | 1154 | |10 | B | 1345 | |11 | B | 1221 | |12 | B | 234 | |13 | C | 2345 | |14 | C | 2645 | |15 | C | 2645 | |16 | C | 2652 | |17 | C | 65 | +-----+------------+--------+ Write a SQL query to find the median salary of each company. Bonus points if you can solve it without using any built-in SQL functions. +-----+------------+--------+ |Id | Company | Salary | +-----+------------+--------+ |5 | A | 451 | |6 | A | 513 | |12 | B | 234 | |9 | B | 1154 | |14 | C | 2645 | +-----+------------+--------+
SELECT * FROM employee AS E WHEREABS( (SELECTCOUNT(Id) FROM Employee AS E1 WHERE E1.Company = E.Company AND E1.Salary <= E.Salary) - (SELECTCOUNT(Id) FROM Employee AS E2 WHERE E2.Company = E.Company AND E2.Salary >= E.Salary) ) <= 1 GROUPBY Company, Salary;
571 Find Median Given Frequency of Numbers 给定数字的频率查询中位数
题目描述:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
The Numbers table keeps the value of number and its frequency.
+----------+-------------+ | Number | Frequency | +----------+-------------| | 0 | 7 | | 1 | 1 | | 2 | 3 | | 3 | 1 | +----------+-------------+ In this table, the numbers are 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, so the median is (0 + 0) / 2 = 0.
+--------+ | median | +--------| | 0.0000 | +--------+ Write a query to find the median of all numbers and name the result as median.
解题思路:这个还没搞懂,代码抄别人的。。
通过代码:
1 2 3 4
SELECTAVG(n.Number) ASmedian FROM Numbers n WHERE n.Frequency >= ABS((SELECTSUM(Frequency) FROM Numbers WHERENumber <= n.Number) - (SELECTSUM(Frequency) FROM Numbers WHERENumber >= n.Number))
579 Find Cumulative Salary of an Employee 查询员工的累计薪水
Explanation Employee '1' has 3 salary records for the following 3 months except the most recent month '4': salary 40 for month '3', 30 for month '2' and 20 for month '1' So the cumulative sum of salary of this employee over 3 months is 90(40+30+20), 50(30+20) and 20 respectively.
| Id | Month | Salary | |----|-------|--------| | 1 | 3 | 90 | | 1 | 2 | 50 | | 1 | 1 | 20 | Employee '2' only has one salary record (month '1') except its most recent month '2'. | Id | Month | Salary | |----|-------|--------| | 2 | 1 | 20 |
Employ '3' has two salary records except its most recent pay month '4': month '3' with 60 and month '2' with 40. So the cumulative salary is as following. | Id | Month | Salary | |----|-------|--------| | 3 | 3 | 100 | | 3 | 2 | 40 |
解题思路:
通过代码:
第一种方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
SELECT a.id, a.month, SUM(b.salary) Salary FROM Employee a JOIN Employee b ON a.id = b.id AND a.month - b.month >= 0AND a.month - b.month < 3 GROUPBY a.id, a.month HAVING (a.id, a.month) NOTIN (SELECTid, MAX(month) FROM Employee GROUPBYid) ORDERBY a.id, a.month DESC
第二种方法:
1 2 3 4 5
SELECT e1.Id, MAX(e2.Month) ASMonth, SUM(e2.Salary) AS Salary FROM Employee e1, Employee e2 WHERE e1.Id = e2.Id AND e2.Month BETWEEN (e1.Month - 3) AND (e1.Month - 1) GROUPBY e1.Id, e1.Month ORDERBYId, MonthDESC;
615 Average Salary: Departments VS Company 平均工资:部门与公司比较
Explanation In March, the company's average salary is (9000+6000+10000)/3 = 8333.33...
The average salary for department '1' is 9000, which is the salary of employee_id '1' since there is only one employee in this department. So the comparison result is 'higher' since 9000 > 8333.33 obviously. The average salary of department '2' is (6000 + 10000)/2 = 8000, which is the average of employee_id '2' and '3'. So the comparison result is 'lower' since 8000 < 8333.33.
With he same formula for the average salary comparison in February, the result is 'same' since both the department '1' and '2' have the same average salary with the company, which is 7000.
解题思路:显示部门员工平均工资与公司平均工资的比较结果(更高/更低/相同)。
那么先找出公司每个月的平均工资:
1 2 3 4 5 6
SELECT *, AVG(amount) AS`avg_salary` FROM salary AS s JOIN employee AS e ON s.employee_id = e.employee_id GROUPBYLEFT(s.pay_date, 7) ORDERBYLEFT(s.pay_date, 7) DESC ;
SELECT *, AVG(amount) AS`dept_avg_salary` FROM salary AS s JOIN employee AS e ON s.employee_id = e.employee_id GROUPBYLEFT(s.pay_date, 7), e.department_id ORDERBYLEFT(s.pay_date, 7) DESC ;
SELECT * FROM ( SELECTDATE_FORMAT(pay_date, '%Y-%m') AS pay_month, AVG(amount) AS`avg_salary` FROM salary AS s JOIN employee AS e ON s.employee_id = e.employee_id GROUPBY pay_month ) AS A JOIN ( SELECT e.department_id, DATE_FORMAT(pay_date, '%Y-%m') AS pay_month, AVG(amount) AS`dept_avg_salary` FROM salary AS s JOIN employee AS e ON s.employee_id = e.employee_id GROUPBY pay_month, e.department_id ) AS B ON A.pay_month = B.pay_month ORDERBY B.pay_month DESC, B.department_id;
SELECT B.pay_month, B.department_id, CASE WHEN B.dept_avg_salary > A.avg_salary THEN'higher' WHEN B.dept_avg_salary < A.avg_salary THEN'lower' ELSE'same' ENDAS'comparison'
FROM ( SELECTDATE_FORMAT(pay_date, '%Y-%m') AS pay_month, AVG(amount) AS`avg_salary` FROM salary AS s JOIN employee AS e ON s.employee_id = e.employee_id GROUPBY pay_month ) AS A JOIN ( SELECT e.department_id, DATE_FORMAT(pay_date, '%Y-%m') AS pay_month, AVG(amount) AS`dept_avg_salary` FROM salary AS s JOIN employee AS e ON s.employee_id = e.employee_id GROUPBY pay_month, e.department_id ) AS B ON A.pay_month = B.pay_month ORDERBY B.pay_month DESC, B.department_id;
A U.S graduate school has students from Asia, Europe and America. The students' location information are stored in table student as below.
| name | continent | |--------|-----------| | Jack | America | | Pascal | Europe | | Xi | Asia | | Jane | America |
Pivot the continent column in this table so that each name is sorted alphabetically and displayed underneath its corresponding continent. The output headers should be America, Asia and Europe respectively. It is guaranteed that the student number from America is no less than either Asia or Europe.
For the sample input, the output is:
| America | Asia | Europe | |---------|------|--------| | Jack | Xi | Pascal | | Jane | | | Follow-up: If it is unknown which continent has the most students, can you write a query to generate the student report?
解题思路:这个是行转列问题,但是我没有思路怎么做。。看网上的方法是这样的
第一种思路,使用自定义变量,
1 2 3 4
SELECT @am := @am + 1AS row_id, nameAS America FROM student, (SELECT @am := 0) AS init WHERE continent = 'America' ORDERBYname;
得到结果如下:
1 2 3 4 5 6
+--------+---------+ | row_id | America | +--------+---------+ | 1 | Jack | | 2 | Jane | +--------+---------+
SELECT a.name AS America, b.name AS Asia, c.name AS Europe FROM ( SELECT @r1 := @r1 + 1ASid, name FROM student, (SELECT @r1 := 0) init WHERE continent = 'America' ORDERBYname ) a LEFTJOIN ( SELECT @r2 := @r2 + 1ASid, name FROM student, (SELECT @r2 := 0) init WHERE continent = 'Asia' ORDERBYname ) b ON a.id = b.id LEFTJOIN ( SELECT @r3 := @r3 + 1ASid, name FROM student, (SELECT @r3 := 0) init WHERE continent = 'Europe' ORDERBYname ) c ON a.id = c.id OR b.id = c.id;
第二种思路,使用窗口函数。
1 2 3 4 5 6 7 8 9 10 11 12 13
SELECT America, Asia, Europe FROM( SELECT continentorder, MAX(CASEWHEN continent = 'America'THENnameEND )AS America, MAX(CASEWHEN continent = 'Europe'THENnameEND )AS Europe, MAX(CASEWHEN continent = 'Asia'THENnameEND )AS Asia FROM ( SELECT *, ROW_NUMBER()OVER(PARTITIONBY continent ORDERBYname) AS continentorder FROM student ) ASSOURCE GROUPBY continentorder )temp;
+--------------+---------+ | Column Name | Type | +--------------+---------+ | player_id | int | | device_id | int | | event_date | date | | games_played | int | +--------------+---------+ (player_id, event_date) is the primary key of this table. This table shows the activity of players of some game. Each row is a record of a player who logged in and played a number of games (possibly 0) before logging out on some day using some device.
We define the install date of a player to be the first login day of that player.
We also define day 1 retention of some date X to be the number of players whose install date is X and they logged back in on the day right after X, divided by the number of players whose install date is X, rounded to 2 decimal places.
Write an SQL query that reports for each install date, the number of players that installed the game on that day and the day 1 retention.
The query result format is in the following example:
Result table: +------------+----------+----------------+ | install_dt | installs | Day1_retention | +------------+----------+----------------+ | 2016-03-01 | 2 | 0.50 | | 2017-06-25 | 1 | 0.00 | +------------+----------+----------------+ Player 1 and 3 installed the game on 2016-03-01 but only player 1 logged back in on 2016-03-02 so the day 1 retention of 2016-03-01 is 1 / 2 = 0.50 Player 2 installed the game on 2017-06-25 but didn't log back in on 2017-06-26 so the day 1 retention of 2017-06-25 is 0 / 1 = 0.00
解题思路:找出每个玩家的安装日期,以及安装日期后的一日留存。
首先找出每个玩家的安装日期,即第一次登陆的日期,对玩家分组,求每组的最小日期。
1 2 3
SELECT player_id, MIN(event_date) AS'install_dt' FROM Activity GROUPBY player_id;
SELECT * FROM ( SELECT player_id, MIN(event_date) AS'install_dt' FROM Activity GROUPBY player_id ) AS A LEFTJOIN Activity AS B ON A.player_id = B.player_id AND B.event_date = DATE_ADD(A.install_dt, INTERVAL1DAY);
SELECT install_dt, COUNT(player_id) AS installs, ROUND( COUNT(next_day) / COUNT(player_id), 2 ) AS Day1_retention FROM ( SELECT A.player_id, A.install_dt, B.event_date AS'next_day' FROM ( SELECT player_id, MIN(event_date) AS'install_dt' FROM Activity GROUPBY player_id ) AS A LEFTJOIN Activity AS B ON A.player_id = B.player_id AND B.event_date = DATE_ADD(A.install_dt,INTERVAL1DAY) ) AS t GROUPBY install_dt;
+-------------+---------+ | Column Name | Type | +-------------+---------+ | user_id | int | | spend_date | date | | platform | enum | | amount | int | +-------------+---------+ The table logs the spendings history of users that make purchases from an online shopping website which has a desktop and a mobile application. (user_id, spend_date, platform) is the primary key of this table. The platform column is an ENUM type of ('desktop', 'mobile'). Write an SQL query to find the total number of users and the total amount spent using mobile only, desktop only and both mobile and desktop together for each date.
The query result format is in the following example:
Result table: +------------+----------+--------------+-------------+ | spend_date | platform | total_amount | total_users | +------------+----------+--------------+-------------+ | 2019-07-01 | desktop | 100 | 1 | | 2019-07-01 | mobile | 100 | 1 | | 2019-07-01 | both | 200 | 1 | | 2019-07-02 | desktop | 100 | 1 | | 2019-07-02 | mobile | 100 | 1 | | 2019-07-02 | both | 0 | 0 | +------------+----------+--------------+-------------+ On 2019-07-01, user 1 purchased using both desktop and mobile, user 2 purchased using mobile only and user 3 purchased using desktop only. On 2019-07-02, user 2 purchased using mobile only, user 3 purchased using desktop only and no one purchased using both platforms.
解题思路:
首先按照spend_date和user_id分组,统计平台信息,如果两个平台都有,就设为both
1 2 3 4 5 6 7 8 9 10
SELECT spend_date, user_id, (CASECOUNT(DISTINCT platform) WHEN1THEN platform WHEN2THEN'both' END) AS platform, SUM(amount) AS amount FROM spending GROUPBY spend_date, user_id;
SELECT spend_date, platform, SUM(amount) AS total_amount, COUNT(user_id) AS total_users FROM ( SELECT spend_date, user_id, (CASECOUNT(DISTINCT platform) WHEN1THEN platform WHEN2THEN'both' END) AS platform, SUM(amount) AS amount FROM spending GROUPBY spend_date, user_id ) AS b GROUPBY spend_date, platform;
SELECT'desktop'AS platform UNION SELECT'mobile'AS platform UNION SELECT'both'AS platform;
得到结果:
1 2 3 4 5 6 7
+----------+ | platform | +----------+ | desktop | | mobile | | both | +----------+
连接表:
1 2 3 4 5 6
SELECTDISTINCT(spend_date), a.platform FROM Spending JOIN ( SELECT'desktop'AS platform UNION SELECT'mobile'AS platform UNION SELECT'both'AS platform ) AS a
得到结果:
1 2 3 4 5 6 7 8 9 10
+------------+----------+ | spend_date | platform | +------------+----------+ | 2019-07-01 | desktop | | 2019-07-01 | mobile | | 2019-07-01 | both | | 2019-07-02 | desktop | | 2019-07-02 | mobile | | 2019-07-02 | both | +------------+----------+
SELECT * FROM ( SELECTDISTINCT(spend_date), a.platform -- table aa FROM Spending JOIN ( SELECT'desktop'AS platform UNION SELECT'mobile'AS platform UNION SELECT'both'AS platform ) AS a ) AS ta LEFTJOIN ( SELECT spend_date, platform, SUM(amount) AS total_amount, COUNT(user_id) AS total_users FROM ( SELECT spend_date, user_id, (CASECOUNT(DISTINCT platform) WHEN1THEN platform WHEN2THEN'both' END) AS platform, SUM(amount) AS amount FROM spending GROUPBY spend_date, user_id ) AS b GROUPBY spend_date, platform ) as tb ON ta.platform = tb.platform AND ta.spend_date = tb.spend_date;
SELECT ta.spend_date, ta.platform, COALESCE(tb.total_amount, 0) AS total_amount, COALESCE(tb.total_users, 0) AS total_users FROM ( SELECTDISTINCT(spend_date), a.platform -- table aa FROM Spending JOIN ( SELECT'desktop'AS platform UNION SELECT'mobile'AS platform UNION SELECT'both'AS platform ) AS a ) AS ta LEFTJOIN ( SELECT spend_date, platform, SUM(amount) AS total_amount, COUNT(user_id) AS total_users FROM ( SELECT spend_date, user_id, (CASECOUNT(DISTINCT platform) WHEN1THEN platform WHEN2THEN'both' END) AS platform, SUM(amount) AS amount FROM spending GROUPBY spend_date, user_id ) AS b GROUPBY spend_date, platform ) as tb ON ta.platform = tb.platform AND ta.spend_date = tb.spend_date ORDERBY spend_date, total_users DESC, total_amount;
+----------------+---------+ | Column Name | Type | +----------------+---------+ | user_id | int | | join_date | date | | favorite_brand | varchar | +----------------+---------+ user_id is the primary key of this table. This table has the info of the users of an online shopping website where users can sell and buy items. Table: Orders
+---------------+---------+ | Column Name | Type | +---------------+---------+ | order_id | int | | order_date | date | | item_id | int | | buyer_id | int | | seller_id | int | +---------------+---------+ order_id is the primary key of this table. item_id is a foreign key to the Items table. buyer_id and seller_id are foreign keys to the Users table. Table: Items
+---------------+---------+ | Column Name | Type | +---------------+---------+ | item_id | int | | item_brand | varchar | +---------------+---------+ item_id is the primary key of this table.
Write an SQL query to find for each user, whether the brand of the second item (by date) they sold is their favorite brand. If a user sold less than two items, report the answer for that user as no.
It is guaranteed that no seller sold more than one item on a day.
The query result format is in the following example:
Result table: +-----------+--------------------+ | seller_id | 2nd_item_fav_brand | +-----------+--------------------+ | 1 | no | | 2 | yes | | 3 | yes | | 4 | no | +-----------+--------------------+
The answer for the user with id 1 is no because they sold nothing. The answer for the users with id 2 and 3 is yes because the brands of their second sold items are their favorite brands. The answer for the user with id 4 is no because the brand of their second sold item is not their favorite brand.
解题思路:
通过代码:
1 2 3 4 5 6 7 8 9 10 11 12
SELECT user_id AS seller_id, IF(item_brand = favorite_brand, 'yes', 'no') AS2nd_item_fav_brand FROM (SELECT user_id, favorite_brand, (SELECT item_id FROM orders o WHERE user_id = o.seller_id ORDERBY order_date limit1, 1) AS item_id FROMusers) AS u LEFTJOIN items AS i ON u.item_id = i.item_id ORDERBY seller_id;
+-------------+-------+ | Column Name | Type | +-------------+-------+ | player_id | int | | group_id | int | +-------------+-------+ player_id is the primary key of this table. Each row of this table indicates the group of each player. Table: Matches
+---------------+---------+ | Column Name | Type | +---------------+---------+ | match_id | int | | first_player | int | | second_player | int | | first_score | int | | second_score | int | +---------------+---------+ match_id is the primary key of this table. Each row is a record of a match, first_player and second_player contain the player_id of each match. first_score and second_score contain the number of points of the first_player and second_player respectively. You may assume that, in each match, players belongs to the same group.
The winner in each group is the player who scored the maximum total points within the group. In the case of a tie, the lowest player_id wins.
Write an SQL query to find the winner in each group.
The query result format is in the following example:
SELECT p.group_id, ps.player_id, SUM(ps.score) AS score FROM Players AS p INNERJOIN ( SELECT first_player AS player_id, first_score AS score FROM Matches UNIONALL SELECT second_player AS player_id, second_score AS score FROM Matches ) AS ps ON p.player_id = ps.player_id GROUPBY ps.player_id ORDERBYgroup_id, score DESC, player_id;
SELECT group_id, player_id FROM ( SELECT p.group_id, ps.player_id, SUM(ps.score) AS score FROM Players AS p INNERJOIN ( SELECT first_player AS player_id, first_score AS score FROM Matches UNIONALL SELECT second_player AS player_id, second_score AS score FROM Matches ) AS ps ON p.player_id = ps.player_id GROUPBY ps.player_id ORDERBYgroup_id, score DESC, player_id ) AS top_scores GROUPBYgroup_id;
+--------------+---------+ | Column Name | Type | +--------------+---------+ | fail_date | date | +--------------+---------+ Primary key for this table is fail_date. Failed table contains the days of failed tasks. Table: Succeeded
+--------------+---------+ | Column Name | Type | +--------------+---------+ | success_date | date | +--------------+---------+ Primary key for this table is success_date. Succeeded table contains the days of succeeded tasks.
A system is running one task every day. Every task is independent of the previous tasks. The tasks can fail or succeed.
Write an SQL query to generate a report of period_state for each continuous interval of days in the period from 2019-01-01 to 2019-12-31.
period_state is 'failed' if tasks in this interval failed or 'succeeded' if tasks in this interval succeeded. Interval of days are retrieved as start_date and end_date.
Order result by start_date.
The query result format is in the following example:
The report ignored the system state in 2018 as we care about the system in the period 2019-01-01 to 2019-12-31. From 2019-01-01 to 2019-01-03 all tasks succeeded and the system state was "succeeded". From 2019-01-04 to 2019-01-05 all tasks failed and system state was "failed". From 2019-01-06 to 2019-01-06 all tasks succeeded and system state was "succeeded".
SELECT * FROM ( SELECT fail_date ASdate, 'failed'AS state FROMFailed UNIONALL SELECT success_date ASdate, 'succeeded'AS state FROM Succeeded ) AS a WHEREdateBETWEEN'2019-01-01'AND'2019-12-31' ORDERBYdate;
SELECT * FROM ( SELECT * FROM ( SELECT fail_date ASdate, 'failed'AS state FROMFailed UNIONALL SELECT success_date ASdate, 'succeeded'AS state FROM Succeeded ) AS a WHEREdateBETWEEN'2019-01-01'AND'2019-12-31' ORDERBYdate ) AS b, ( SELECT @rank := 0, @prev := "unkonwn"
SELECT state, date, @rank := CASE WHEN @prev = state THEN @rank ELSE @rank + 1 ENDASrank, @prev := state AS prev FROM ( SELECT * FROM ( SELECT fail_date ASdate, 'failed'AS state FROMFailed UNIONALL SELECT success_date ASdate, 'succeeded'AS state FROM Succeeded ) AS a WHEREdateBETWEEN'2019-01-01'AND'2019-12-31' ORDERBYdate ) AS b, ( SELECT @rank := 0, @prev := "unkonwn"
SELECT state AS period_state, MIN(date) AS start_date, MAX(date) AS end_date FROM ( SELECT state, date, @rank := CASE WHEN @prev = state THEN @rank ELSE @rank + 1 ENDASrank, @prev := state AS prev FROM ( SELECT * FROM ( SELECT fail_date ASdate, 'failed'AS state FROMFailed UNIONALL SELECT success_date ASdate, 'succeeded'AS state FROM Succeeded ) AS a WHEREdateBETWEEN'2019-01-01'AND'2019-12-31' ORDERBYdate ) AS b, ( SELECT @rank := 0, @prev := "unkonwn"