sql力扣刷题八

1378. 使用唯一标识码替换员工ID
Create table If Not Exists Employees (id int, name varchar(20))
Create table If Not Exists EmployeeUNI (id int, unique_id int)
Truncate table Employees
insert into Employees (id, name) values ('1', 'Alice')
insert into Employees (id, name) values ('7', 'Bob')
insert into Employees (id, name) values ('11', 'Meir')
insert into Employees (id, name) values ('90', 'Winston')
insert into Employees (id, name) values ('3', 'Jonathan')
Truncate table EmployeeUNI
insert into EmployeeUNI (id, unique_id) values ('3', '1')
insert into EmployeeUNI (id, unique_id) values ('11', '2')
insert into EmployeeUNI (id, unique_id) values ('90', '3')

Employees 表:

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| name          | varchar |
+---------------+---------+
id 是这张表的主键。
这张表的每一行分别代表了某公司其中一位员工的名字和 ID 。

EmployeeUNI 表:

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| unique_id     | int     |
+---------------+---------+
(id, unique_id) 是这张表的主键。
这张表的每一行包含了该公司某位员工的 ID 和他的唯一标识码(unique ID)。

写一段SQL查询来展示每位用户的 唯一标识码(unique ID );如果某位员工没有唯一标识码,使用 null 填充即可。

你可以以 任意 顺序返回结果表。

查询结果的格式如下例所示。

示例 1:

输入:
Employees 表:
+----+----------+
| id | name     |
+----+----------+
| 1  | Alice    |
| 7  | Bob      |
| 11 | Meir     |
| 90 | Winston  |
| 3  | Jonathan |
+----+----------+
EmployeeUNI 表:
+----+-----------+
| id | unique_id |
+----+-----------+
| 3  | 1         |
| 11 | 2         |
| 90 | 3         |
+----+-----------+
输出:
+-----------+----------+
| unique_id | name     |
+-----------+----------+
| null      | Alice    |
| null      | Bob      |
| 2         | Meir     |
| 3         | Winston  |
| 1         | Jonathan |
+-----------+----------+
解释:
Alice and Bob 没有唯一标识码, 因此我们使用 null 替代。
Meir 的唯一标识码是 2 。
Winston 的唯一标识码是 3 。
Jonathan 唯一标识码是 1

题解一

SELECT IFNULL(e2.unique_id, NULL) AS 'unique_id',
    e1.name AS 'name'
FROM Employees AS e1
    LEFT OUTER JOIN EmployeeUNI AS e2
    ON e1.id = e2.id
;
select unique_id,name from Employees e left join EmployeeUNI en on e.id = en.id; 
1384. 按年度列出销售总额
Create table If Not Exists Product (product_id int, product_name varchar(30))
Create table If Not Exists Sales (product_id int, period_start date, period_end date, average_daily_sales int)
Truncate table Product
insert into Product (product_id, product_name) values ('1', 'LC Phone ')
insert into Product (product_id, product_name) values ('2', 'LC T-Shirt')
insert into Product (product_id, product_name) values ('3', 'LC Keychain')
Truncate table Sales
insert into Sales (product_id, period_start, period_end, average_daily_sales) values ('1', '2019-01-25', '2019-02-28', '100')
insert into Sales (product_id, period_start, period_end, average_daily_sales) values ('2', '2018-12-01', '2020-01-01', '10')
insert into Sales (product_id, period_start, period_end, average_daily_sales) values ('3', '2019-12-01', '2020-01-31', '1')

Product 表:

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| product_id    | int     |
| product_name  | varchar |
+---------------+---------+
product_id 是这张表的主键。
product_name 是产品的名称。

Sales 表:

+---------------------+---------+
| Column Name         | Type    |
+---------------------+---------+
| product_id          | int     |
| period_start        | date    |
| period_end          | date    |
| average_daily_sales | int     |
+---------------------+---------+
product_id 是这张表的主键。
period_start 和 period_end 是该产品销售期的起始日期和结束日期,且这两个日期包含在销售期内。
average_daily_sales 列存储销售期内该产品的日平均销售额。

编写一段 SQL 查询每个产品每年的总销售额,并包含 product_id, product_name 以及 report_year 等信息。

销售年份的日期介于 2018 年到 2020 年之间。你返回的结果需要按 product_id 和 report_year 排序。

查询结果格式如下例所示。

示例 1:

输入:
Product table:
+------------+--------------+
| product_id | product_name |
+------------+--------------+
| 1          | LC Phone     |
| 2          | LC T-Shirt   |
| 3          | LC Keychain  |
+------------+--------------+
Sales table:
+------------+--------------+-------------+---------------------+
| product_id | period_start | period_end  | average_daily_sales |
+------------+--------------+-------------+---------------------+
| 1          | 2019-01-25   | 2019-02-28  | 100                 |
| 2          | 2018-12-01   | 2020-01-01  | 10                  |
| 3          | 2019-12-01   | 2020-01-31  | 1                   |
+------------+--------------+-------------+---------------------+
输出:
+------------+--------------+-------------+--------------+
| product_id | product_name | report_year | total_amount |
+------------+--------------+-------------+--------------+
| 1          | LC Phone     |    2019     | 3500         |
| 2          | LC T-Shirt   |    2018     | 310          |
| 2          | LC T-Shirt   |    2019     | 3650         |
| 2          | LC T-Shirt   |    2020     | 10           |
| 3          | LC Keychain  |    2019     | 31           |
| 3          | LC Keychain  |    2020     | 31           |
+------------+--------------+-------------+--------------+
解释:
LC Phone 在 2019-01-252019-02-28 期间销售,该产品销售时间总计35天。销售总额 35*100 = 3500。
LC T-shirt 在 2018-12-012020-01-01 期间销售,该产品在2018年、2019年、2020年的销售时间分别是31天、365天、1天,2018年、2019年、2020年的销售总额分别是31*10=310365*10=36501*10=10。
LC Keychain 在 2019-12-012020-01-31 期间销售,该产品在2019年、2020年的销售时间分别是:31天、31天,2019年、2020年的销售总额分别是31*1=3131*1=31

题解一

select s.product_id, p.product_name, y.year report_year, s.average_daily_sales * (if(year(s.period_end) > y.year, y.days_of_year, dayofyear(s.period_end)) - if(year(s.period_start) < y.year, 1, dayofyear(s.period_start)) + 1) total_amount
from Sales s
inner join (
    select '2018' year, 365 days_of_year
    union all select '2019' year, 365 days_of_year
    union all select '2020' year, 366 days_of_year
) y on year(s.period_start) <= y.year and year(s.period_end) >= y.year
inner join Product p on p.product_id = s.product_id
order by s.product_id, y.year

题解二

with recursive Dates(dates) as
(
    select min(period_start) 
    from Sales 
    union all 
    select  dates + interval 1 day from Dates
    where dates + interval 1 day <= (select max(period_end) from Sales)

),
Trans as
(
    select s.product_id,product_name,period_start,period_end,average_daily_sales
    from Sales s 
    left join Product p 
    on s.product_id = p.product_id
)
select product_id,product_name,date_format(dates,'%Y') as report_year 
        ,sum(average_daily_sales) total_amount
from Dates 
join Trans
on dates between period_start and period_end
and date_format(dates,'%Y') between  "2018" and  "2020" 
group by product_id,product_name,report_year
order by product_id,report_year 

题解三

select t.product_id,p.product_name,report_year,
sum(average_daily_sales*(total_days+1)) as total_amount
from product p 
join (
select product_id,average_daily_sales, '2018' as report_year, 
case 
when period_start<='2018-01-01' and period_end>'2018-12-31' then datediff('2018-12-31','2018-01-01') 
when period_start<='2018-01-01' and period_end>='2018-01-01'and period_end<='2018-12-31' then datediff(period_end,'2018-01-01') 
when period_start>'2018-01-01' and period_start<='2018-12-31'and period_end>'2018-12-31' then datediff('2018-12-31',period_start) 
when period_start>'2018-01-01' and period_start<='2018-12-31' and period_end<'2018-12-31' then datediff(period_end,period_start)  
end as total_days
from sales
union all 
select product_id,average_daily_sales, '2019' as report_year, 
case 
when period_start<='2019-01-01' and period_end>'2019-12-31' then datediff('2019-12-31','2019-01-01') 
when period_start<='2019-01-01' and period_end>='2019-01-01'and period_end<='2019-12-31' then datediff(period_end,'2019-01-01') 
when period_start>'2019-01-01' and period_start<='2019-12-31'and period_end>'2019-12-31' then datediff('2019-12-31',period_start) 
when period_start>'2019-01-01' and period_start<='2019-12-31' and period_end<'2019-12-31' then datediff(period_end,period_start)  
end as total_days
from sales
union all 
select product_id,average_daily_sales, '2020' as report_year, 
case 
when period_start<='2020-01-01' and period_end>'2020-12-31' then datediff('2020-12-31','2020-01-01') 
when period_start<='2020-01-01' and period_end>='2020-01-01'and period_end<='2020-12-31' then datediff(period_end,'2020-01-01') 
when period_start>'2020-01-01' and period_start<='2020-12-31'and period_end>'2020-12-31' then datediff('2020-12-31',period_start) 
when period_start>'2020-01-01' and period_start<='2020-12-31' and period_end<'2020-12-31' then datediff(period_end,period_start)  
end as total_days
from sales) t 
on t.product_id=p.product_id
where total_days is not null 
group by 1,3
order by 1,3
1398. 购买了产品 A 和产品 B 却没有购买产品 C 的顾客
Create table If Not Exists Customers (customer_id int, customer_name varchar(30))
Create table If Not Exists Orders (order_id int, customer_id int, product_name varchar(30))
Truncate table Customers
insert into Customers (customer_id, customer_name) values ('1', 'Daniel')
insert into Customers (customer_id, customer_name) values ('2', 'Diana')
insert into Customers (customer_id, customer_name) values ('3', 'Elizabeth')
insert into Customers (customer_id, customer_name) values ('4', 'Jhon')
Truncate table Orders
insert into Orders (order_id, customer_id, product_name) values ('10', '1', 'A')
insert into Orders (order_id, customer_id, product_name) values ('20', '1', 'B')
insert into Orders (order_id, customer_id, product_name) values ('30', '1', 'D')
insert into Orders (order_id, customer_id, product_name) values ('40', '1', 'C')
insert into Orders (order_id, customer_id, product_name) values ('50', '2', 'A')
insert into Orders (order_id, customer_id, product_name) values ('60', '3', 'A')
insert into Orders (order_id, customer_id, product_name) values ('70', '3', 'B')
insert into Orders (order_id, customer_id, product_name) values ('80', '3', 'D')
insert into Orders (order_id, customer_id, product_name) values ('90', '4', 'C')

Customers 表:

+---------------------+---------+
| Column Name         | Type    |
+---------------------+---------+
| customer_id         | int     |
| customer_name       | varchar |
+---------------------+---------+
customer_id 是这张表的主键。
customer_name 是顾客的名称。

Orders 表:

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| order_id      | int     |
| customer_id   | int     |
| product_name  | varchar |
+---------------+---------+
order_id 是这张表的主键。
customer_id 是购买了名为 "product_name" 产品顾客的id。

请你设计 SQL 查询来报告购买了产品 A 和产品 B 却没有购买产品 C 的顾客的 ID 和姓名( customer_id 和 customer_name ),我们将基于此结果为他们推荐产品 C 。
您返回的查询结果需要按照 customer_id 排序。

查询结果如下例所示。

Customers table:
+-------------+---------------+
| customer_id | customer_name |
+-------------+---------------+
| 1           | Daniel        |
| 2           | Diana         |
| 3           | Elizabeth     |
| 4           | Jhon          |
+-------------+---------------+

Orders table:
+------------+--------------+---------------+
| order_id   | customer_id  | product_name  |
+------------+--------------+---------------+
| 10         |     1        |     A         |
| 20         |     1        |     B         |
| 30         |     1        |     D         |
| 40         |     1        |     C         |
| 50         |     2        |     A         |
| 60         |     3        |     A         |
| 70         |     3        |     B         |
| 80         |     3        |     D         |
| 90         |     4        |     C         |
+------------+--------------+---------------+

Result table:
+-------------+---------------+
| customer_id | customer_name |
+-------------+---------------+
| 3           | Elizabeth     |
+-------------+---------------+
只有 customer_id 为 3 的顾客购买了产品 A 和产品 B ,却没有购买产品 C 。

题解一

SELECT o.customer_id customer_id,
        c.customer_name customer_name
FROM Orders o
LEFT JOIN Customers c  USING(customer_id)
GROUP BY customer_id
HAVING 
        SUM(IF(product_name='A',1,0))>0 AND
        SUM(IF(product_name='B',1,0))>0 AND
        SUM(IF(product_name='C',1,0))=0

题解二

select customer_id, customer_name
from Customers 
where customer_id in (
select 
	customer_id
from Orders
group by customer_id
having 
	group_concat(distinct product_name) REGEXP '^A,B$|^A,B,[^C].*'
)

题解三

select c.customer_id, customer_name
from Customers c
where exists(
    select 1 from Orders o1 
    where c.customer_id=o1.customer_id and o1.product_name = 'A'
) and exists(
    select 1 from Orders o2 
    where c.customer_id=o2.customer_id and o2.product_name = 'B'
) and not exists(
    select 1 from Orders o3 
    where c.customer_id=o3.customer_id and o3.product_name = 'C'
)
order by customer_id

题解四

SELECT * FROM Customers
WHERE customer_id IN (
    SELECT customer_id
    FROM Customers
    WHERE customer_id IN (
        SELECT customer_id FROM Orders
        WHERE product_name = 'A' )
    AND customer_id IN (
        SELECT customer_id FROM Orders
        WHERE product_name = 'B' )
    AND customer_id NOT IN (
        SELECT customer_id FROM Orders
        WHERE product_name = 'C' )
)

题解五

SELECT customer_id, customer_name
FROM Orders 
    LEFT JOIN Customers
    USING(customer_id) 
GROUP BY customer_id
    HAVING SUM(product_name = 'A') * SUM(product_name = 'B') > 0
    AND SUM(product_name = 'C') = 0
ORDER BY customer_id

题解六

SELECT customer_id, customer_name
FROM Customers
WHERE customer_id IN (
    SELECT customer_id 
    FROM (  SELECT customer_id,
            (CASE WHEN product_name='A' THEN 100
                  WHEN product_name='B' THEN 10
                  WHEN product_name='C' THEN 1
             END ) AS product_num
            FROM Orders
         ) TT
    GROUP BY customer_id
    HAVING SUM( DISTINCT product_num ) = 110
    -- 注意DISTINCT,因为一个顾客可能买过多次同一产品
);

题解七

SELECT
    c.customer_id, c.customer_name
FROM
    Orders o LEFT JOIN Customers c ON o.customer_id = c.customer_id
GROUP BY c.customer_id
HAVING
    SUM(product_name = 'A') * SUM(product_name = 'B') > 0
    AND SUM(product_name = 'C') = 0
ORDER BY c.customer_id

题解八

# Write your MySQL query statement below
SELECT
    customer_id, customer_name
FROM
    Customers
WHERE
    customer_id NOT IN (
        SELECT customer_id
        FROM Orders
        
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值