1-MySQL基礎和查詢一些特殊業務需求和技巧

在進行復雜業務邏輯sql編寫時,往往理不清多張表之間的連接關係,這時你需要一個清晰的思路來串連多張表。第一個誤區就是根據查詢條件認爲查詢字段所在表爲主表,這是錯誤的,表的連接順序往往是固定的,查詢條件字段所在表是主表是個僞命題。

 

1、根據某個字段分組,但是字段值爲某些值得是有歸爲一組

比如記錄如下:
id status
100 1
101 2
102 3
103 4
104 5
105 99
106 98
將status 5 99 98的歸爲一個組,其他的按status值分組
SELECT
    count(*) as count,
    case when status in (90,98,5) then 5 else status end as optyStatus
from some_test
where `status` is not null
group by case when status in (90,98,5) then 5 else status end

2、2個表間複製數據

INSERT INTO hb_t_nickname1(nickname,gender,is_deleted)
SELECT DISTINCT nickname,gender,is_deleted FROM hb_t_nickname;

3、刪除重複數據

注意:不能重命名

DELETE hb_t_iu from hb_t_iu,(

SELECT
    max(id) id,
    tel
FROM
    hb_t_iu
GROUP BY
    tel    
HAVING
    count( * ) > 1 ) iu2
where hb_t_iu.tel = iu2.tel
and hb_t_iu.id < iu2.id

4、連表更新

UPDATE huc_user huser
inner join hb_t_iu iu on huser.mobile_no = iu.tel
SET huser.gender = iu.gender

5、取餘數

mod(m,n)
m是被取餘的數,n是模

6、計算datetime類型日期和當前時間天數

TIMESTAMPDIFF(YEAR, huser.birth_time, now())

需要注意的是,兩個日期之間的位置和計算規則,第一個時間是beginTime,後一個是endTime,beginTime數值上要比endTime小,否則會出現負數,第一個參數是Unit,取值可以有:

MICROSECOND 微秒
SECOND  秒
MINUTE  分鐘
HOUR   小時
DAY   天
WEEK  星期
MONTH  月
QUARTER  季度
YEAR  年

7、Navicate導出數據時某個字段被處理成無規則串?

查看這個字段類型,longtext有這種情況,使用cast(field as char)轉換一下即可。

8、mysql between and使用

between and 的左右邊界是閉合的,但是在處理時間時需要注意,如果是datetime類型,且入參沒有時間時,時間默認爲00:00:00,如:

select * from t_x where created_time between '2020-01-01' and '2020-01-01';

這樣兩個時間都會是2020-01-01 00:00:00,這樣很可能跟你的預期不符合。

9 trur flase含義

mysql中boolean用tinyint(1)實現,true=1,false=2

select true + 1 // 2

10 mysql varchar 和int比較

2ABC3 =2 // true

2abc > 1 // true

mysql會把字符串類型轉換成數字,從第一個字符開始解析,到第一個字符不符合結束

 

11 count()和sum()

count(expression) 函數,注意入參是表達式

sum(expression) 函數,入參也是表達式

count(*)=count(1) // 統計行數,不管字段是否爲空

count(field) // 字段爲null的會被排除,空串和空白字符依然被計算

sum(field) // 數值類型沒什麼,如果field是varchar,如果存了實數也沒什麼,如果存了非實數字符串,會被解析成0

sum(2) // 是每一列都是2來相加

sum(field=2) // 表達式成立就是true也即1

count(var=2) // 表達式沒有意義了,true或false結果都一樣

12 彙總

select ifnull(a,彙總),count(*) group by a with rollup // 就是彙總

13 一對多連接去重

怎麼處理?

14 查詢表的所有字段

show full columns from t;

15 查詢一張表所有字段飽和度?

16 group by 沒有的字段需要返回?

當查詢簡單時,可以通過構建臨時表完成如:select x union select y union select z構建一個臨時結果作爲主表,但是關聯的表過多時,比如需要通過能關聯上另一張表作爲選中的結果並計算合計,這樣就很難操作了,只能在Java中操作,如何操作,定義一個final List,然後遍歷,將查詢結果集轉換成map,然後構建一個新List返回,這樣即可以填充沒有的字段,還能保證順序,其中List轉Map需要我們掌握。

17 編碼選擇

2、關於字段編碼選擇,有個同事建立的某張表使用了不同的字符編碼,導致大小寫敏感了,相關字段索引也無法使用。mysql字符集默認的編碼查詢:show charset;

如果指定了表的字符集,那麼字段的字符編碼就是默認的了,其中utf8mb4_bin大小寫敏感,使用時注意。

18 date_format()的迷惑點

select DATE_FORMAT('2020-09','%Y-%m') // 輸出null

這種用法有可能出現在前端傳參和已有字段比較的情況,爲什麼輸出null,因爲date_format接受的第一個參數類型是date,至少要有年月日,這裏只有年月,不被認爲是日期,所以格式化無效,直接輸出null,使用的時候需要警惕。

19 MySQL數據庫約束

約束(constraint),使用來保證數據庫中數據完整性(實體完整性(Entity Integrity)、域完整性(Domain Integrity)、參照完整性(Referential Integrity)、用戶定義的完整性(User-definedIntegrity))的手段之一。

MySQL中常用的約束:

約束類型: 主鍵 外鍵 唯一 非空 自增 默認值
關鍵字: primary key foreign key

unique

not null

auto_increment

default

primary key = unique + not null

使用方式如下:

ALTER TABLE `zz` ADD PRIMARY KEY ( `id` ) // 添加主鍵,不需要給主鍵起名字

ALTER TABLE `zz` DROP PRIMARY KEY // 刪主鍵,主鍵不需要名稱,因爲只有一個,此字段不能有自增屬性,否則刪不了。

ALTER TABLE zz ADD CONSTRAINT fk_prod_id FOREIGN KEY (product_id) REFERENCES product (id); // 添加外鍵

ALTER TABLE `zz` DROP FOREIGN KEY `fk_prod_id`; // 刪除外鍵

ALTER TABLE zz ADD UNIQUE KEY uk_2(name,product_id); // 添加唯一約束

ALTER TABLE zz ADD UNIQUE uk_2 (NAME, product_id); // 添加唯一約束可以省略 KEY關鍵字

ALTER TABLE zz ADD CONSTRAINT UNIQUE uk_2 (NAME, product_id); // 添加唯一約束多加一個constraint關鍵字也行

ALTER TABLE zz DROP INDEX uk_2; // 刪除唯一約束,注意這裏已經變成index了

ALTER TABLE zz MODIFY product_id VARCHAR (12) NOT NULL; // 添加非空約束

ALTER TABLE zz MODIFY product_id VARCHAR (12) NULL; // 刪除非空約束

MySQL表中只能設置一個自增長字段【必須是key(其他普通字段不行))】

ALTER TABLE zz MODIFY product_id INT UNSIGNED AUTO_INCREMENT; // 添加自增

ALTER TABLE zz MODIFY product_id INT UNSIGNED;// 刪除自增

20 常用表結構修改

修改字段編碼使支持emoji表情

ALTER TABLE t_user MODIFY `signature` VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL  COMMENT '';

添加單個或多個字段索引

ALTER TABLE table_name ADD INDEX index_name (column_list)
ALTER TABLE table_name ADD UNIQUE (column_list)
ALTER TABLE table_name ADD PRIMARY KEY (column_list)

主鍵一定是索引,索引未必是主鍵,複合主鍵一定建立複合索引,複合主鍵不能重複,每個鍵都不能爲空。

聯合主鍵:指多張表的主鍵組合,多半出現在多對多時的中間表上

複合主鍵:一張表中多個字段組成primary key,一張表只能有一個主鍵,主鍵分爲單一主鍵和複合主鍵

添加字段

ALTER TABLE xxx_yy ADD terminal_type tinyint (2) unsigned DEFAULT '0' COMMENT '註釋';

21 case when 2種用法

-- 簡單case函數
case sex
  when '1' then '男'
  when '2' then '女’
  else '其他' end
-- case搜索函數
case when sex = '1' then '男'
     when sex = '2' then '女'
     else '其他' end

需要注意的是case when搜索函數和 else if功效一樣,當前的滿足了,就不會進行下面的判斷了,使用時需要注意這一點。

 

22 關於連接

1 連接基礎

left join = left outer join

right join = right outer join

inner join = join

full join  = full outer join(left join + right join)

對於left join,條件寫在on後面和where後面是有區別的,寫在on後的不會影響主表記錄,哪怕條件是關於主表的,寫在where後面的條件是針對連接後的結果集,可以影響到主表記錄。如:

SELECT
	u.NAME,
	ur.role_id
FROM
	user_cn u
LEFT JOIN user_role ur ON u.id = ur.user_id AND u.NAME = '張飛' // 這裏的u條件不會影響主表

2 多表連接

SELECT
	u. NAME,
	r.role_name
FROM
	user_cn u
LEFT JOIN user_role ur ON u.id = ur.user_id
INNER JOIN role r ON ur.role_id = r.id

可以看到,多表連接後,如果有left join和inner join同時出現,那麼inner join的排除效果就會體現到主表上了,連接順序對結果是沒有影響的,我們可以看成是inner join和前面所有連接結果再進行運算,那麼自然就會排除。看這種複雜連接關係,可以先分清對應關係,這裏u對ur是一對多(u和ur是多對多),ur對r是一對一。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章