高級字符串函數 / 正則表達式 / 子句
1667. 修復表中的名字
題目鏈接:1667. 修復表中的名字
狀態:學會了
思路:
要求修復名字(首字母大寫,其他字母小寫),按順序返回。
想法就是取出名字這一列,把第一個字母與其他字符分開,分別對應修改大小寫,然后連在一起。
高級字符串函數:
SUBSTRING(column_name, start, length)
:這將從列的值中提取一個子字符串,從指定的起始位置開始,直到指定的長度。
UPPER(expression)
:這會將字符串表達式轉換為大寫。
LOWER(expression)
:這會將字符串表達式轉換為小寫。
CONCAT(string1, string2, ...)
:這會將兩個或多個字符串連接成一個字符串。
select user_id, concat(upper(substring(name, 1, 1)), lower(substring(name, 2)))as name
from Users
order by user_id;
1527. 患某種疾病的患者
題目鏈接:1527. 患某種疾病的患者
狀態:學會了
思路:
需要查詢患I類糖尿病的信息返回。
用 like
簡單模式匹配字符,通配符只有%
(代表任意數量的任意字符)和 _
(代表單個任意字符)。這個問題可以歸結于兩種情況:1.條件代碼以"DIABI"開頭和2.條件代碼包含" DIABI".
select patient_id, patient_name, conditions
from Patients
where conditions like "% DIAB1%" or conditions like "DIAB1%";
196. 刪除重復的電子郵箱
題目鏈接:196. 刪除重復的電子郵箱
狀態:學會了
思路:
要求刪除所有重復的電子郵件(保留id最小的一個)。
1.使用自連接 join
,找到哪些記錄是重復的:email字段字段相同,但是id不同的記錄組合。
2.執行刪除條件 delete
,delete p1
表示我們要刪除p1
表中滿足連接條件的那些行。
delete p1
from Person p1
join Person p2
on p1.email=p2.email and p1.id>p2.id;
176. 第二高的薪水
題目鏈接:176. 第二高的薪水
狀態:學會了
思路:
要找到第二高的不同的薪水,若不存在返回NULL。
第一反應肯定是用到ifnull函數,如salary不存在直接返回null。這是我寫的第一版的代碼,有一個問題是:當不存在rank_sal=2,表是個空的,infull沒有讀取到任何salary的值,所以沒有東西替換,直接就錯了。
select ifnull(salary, NULL) as SecondHighestSalary
from (select salary, (dense_rank() over(order by salary desc)) as rank_salfrom Employee
) a
where rank_sal=2
反思了一下這個寫法,覺得應該把查詢salary整個部分的做成子查詢,放進infull里面。這樣當不存在rank_sal=2,子查詢返回的結果是null,所以ifnull返回null。
select (ifnull ((select distinct salaryfrom (select salary, (dense_rank() over(order by salary desc)) as rank_salfrom Employee) awhere rank_sal=2) , NULL)
) as SecondHighestSalary
1484. 按日期分組銷售產品
題目鏈接:1484. 按日期分組銷售產品
狀態:學會了
思路:
找出每個日期(排序)、銷售的不同產品的數量及名稱(按字典排序)。
1.對日期進行分組,然后用count distinct統計分組的物品數量。
2.對每個組中唯一名稱進行排序和連接,使用的是group_concat()
函數,將分組中的多行的多個值組合成一個字符串。
3.對最后結果的日期進行升序排序。
select sell_date, count(distinct product) as num_sold,group_concat(distinct product order by product separator ',') as products
from Activities
group by sell_date
order by sell_date;
MySQL中GROUP_CONCAT
函數語法:
GROUP_CONCAT(DISTINCT expression1ORDER BY expression2SEPARATOR sep
);
1327. 列出指定時間段內所有的下單產品
題目鏈接:1327. 列出指定時間段內所有的下單產品
狀態:自己寫出來的
思路:
要求在2020年2月份下單數量不少于100的產品的名字和數目。
1.內層子查詢:篩選orders表中日期在2020年2月份的,按照產品id分類,計算產品的累計銷售數目。
2.外層查詢:篩選累計銷售數目大于等于100的,products表左連接子查詢結果,通過on p.product_id=o.product_id關聯,返回名字和累計銷售數目。
select p.product_name, o.sum_unit as unit
from Products p
left join (select product_id, sum(unit) as sum_unitfrom Orderswhere date_format(order_date, "%Y-%m")='2020-02'group by product_id
) o on p.product_id=o.product_id
where o.sum_unit>=100
1517. 查找擁有有效郵箱的用戶
題目鏈接:1517. 查找擁有有效郵箱的用戶
狀態:學會了
思路:
要求返回符合要求的:必須 以字母開頭,剩下可以包含字母(大寫或小寫),數字,下劃線 ‘_’ ,點 ‘.’ 和/或破折號 ‘-’ ,最后必須為 ‘@leetcode.com’ 。
以任何順序返回結果表。
正則表達式 regexp
, 就是 regular expression 正則表達式 的意思:
^
表示以后面的字符為開頭
[]
表示括號內任意字符
-
表示連續
*
表示重復前面任意字符任意次數
\
用來轉義后面的特殊字符,以表示字符原本的樣子,而不是將其作為特殊字符使用
$
表示以前面的字符為結尾
正則表達式里有一些字符被賦予了特殊意義,用于表示特定的匹配規則,若要匹配這些字符本身,就需要使用轉義字符 \。常見的具有特殊含義的字符如下:
元字符:像 .、*、+、?、^、$、(、)、[、]、{、}、|
等。
特定的轉義序列:\d
代表任意數字,\s
代表任意空白字符,\w
代表任意字母、數字或下劃線。
select *
from Users
where mail regexp '^[a-zA-Z][a-zA-Z\_\.\-]+@leetcode\.com$';
一點不著邊際的話
這是第一遍刷,實在是很難判斷出來什么時候用left join,什么時候join,什么時候inner join,什么時候用子查詢,還有MySQL這一大把的奇妙小函數,目前還需要記住關于日期和處理字符串的。