首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 查詢核心:WHERE 條件構建、常用函數與 HAVING 進階用法

     編輯:MySQL 綜合教學

MySQL 查詢核心:WHERE 條件構建、常用函數與 HAVING 進階用法

掌握 WHERE 子句的邏輯構建、常用函數的正確調用、聚合後過濾(HAVING)與 WHERE 的區別,是編寫高性能、正確語義 SQL 的關鍵。本文結合實戰案例系統講解。

一、 WHERE 子句核心邏輯

本質:將表視為行集合,WHERE 後的表達式對每行求值,結果為 TRUE 的行進入結果集。

-- 等價思維:列 = 變量,WHERE = if(exp)
SELECT * FROM goods WHERE 1;          -- 恆真,返回全表
SELECT * FROM goods WHERE category_id = 1 AND price > 100;

二、 列運算與別名

列可直接參與算術運算,結果可作為衍生列使用別名(不可在同層 WHERE 中使用別名)。

SELECT goods_id, goods_name, 
       (market_price - shop_price) AS discount
FROM goods
WHERE (market_price - shop_price) > 50;  -- 必須重複表達式或用子查詢/CTE

正確復用別名:

SELECT * FROM (
    SELECT goods_id, goods_name, (market_price - shop_price) AS discount
    FROM goods
) t WHERE discount > 50;

三、 模糊查詢與通配符

符號含義示例匹配示例
%任意長度字符(含 0)LIKE 'abc%'abc, abcd, abcdef
_單個任意字符LIKE 'ab_'abc, abd, ab1
[]字符集合(需 REGEXP)REGEXP '^ab[cd]'abc, abd

性能警示:LIKE '%kw%' 導致全表掃描,大表必須用全文索引或 ElasticSearch。

四、 常用內建函數分類速查

1. 聚合函數(配合 GROUP BY)

SELECT MAX(price), MIN(price), SUM(amount), AVG(score), COUNT(*)
FROM orders
GROUP BY category_id;

COUNT 細節:COUNT(*) 計行數(含 NULL)、COUNT(col) 計非 NULL 個數、COUNT(DISTINCT col) 計去重非 NULL 個數。

2. 字符串函數

CONCAT('a','b')           -- 'ab'
SUBSTRING('hello', 2, 3)  -- 'ell'
TRIM('  abc  ')           -- 'abc'
UPPER/LOWER               -- 大小寫轉換
REPLACE('a_b_c', '_', '-')-- 'a-b-c'
LENGTH vs CHAR_LENGTH     -- 字節長度 vs 字符長度(多字節字符集區分)

3. 日期時間函數

NOW()                    -- 當前日期時間
CURDATE()                -- 當前日期
DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')
DATEDIFF('2024-12-31', '2024-01-01')  -- 365
DATE_ADD(NOW(), INTERVAL 1 DAY)
TIMESTAMPDIFF(SECOND, '2024-01-01 00:00:00', NOW())

4. 流程控制函數

IF(condition, true_val, false_val)
IFNULL(expr, default_val)      -- expr 為 NULL 返回 default
COALESCE(val1, val2, ...)      -- 返回第一個非 NULL
CASE WHEN cond1 THEN v1 WHEN cond2 THEN v2 ELSE v3 END
NULLIF(expr1, expr2)           -- 相等返回 NULL

5. 數學/加密/資訊函數

ROUND(3.14159, 2)   -- 3.14
CEIL/FLOOR/RAND()
MD5('pass'), SHA2('pass', 256)
VERSION(), CONNECTION_ID(), DATABASE(), USER()

五、 GROUP BY 分組聚合

-- 基礎分組
SELECT cat_id, SUM(goods_number) AS total_stock
FROM goods
GROUP BY cat_id;

-- 多維分組
SELECT cat_id, brand_id, COUNT(*) AS sku_cnt
FROM goods
GROUP BY cat_id, brand_id
WITH ROLLUP;  -- 顯示小計行(cat_id 為 NULL 表示總計)

六、 HAVING vs WHERE:核心區別

維度WHEREHAVING
作用階段分組前,對原始行過濾分組後,對聚合結果過濾
可用列表列、衍生列(不可用聚合函數)分組列、聚合函數、衍生列
索引利用可用索引不可用索引(已聚合)
典型場景業務條件過濾聚合指標閾值過濾

實戰對比

-- WHERE:過濾原始訂單
SELECT user_id, COUNT(*) AS order_cnt
FROM orders
WHERE status = 'paid'          -- 原始行過濾
GROUP BY user_id;

-- HAVING:過濾聚合後的用戶
SELECT user_id, COUNT(*) AS order_cnt
FROM orders
WHERE status = 'paid'
GROUP BY user_id
HAVING COUNT(*) > 10;          -- 聚合結果過濾

-- 組合:WHERE 先縮小數據集,HAVING 再篩選聚合指標
SELECT cat_id, AVG(price) AS avg_price
FROM goods
WHERE is_on_sale = 1           -- 利用索引快速過濾
GROUP BY cat_id
HAVING AVG(price) > 100;       -- 聚合指標篩選

七、 綜合實戰:電商商品篩選頁 SQL

SELECT 
    g.goods_id, g.goods_name, g.shop_price,
    (g.market_price - g.shop_price) AS discount,
    c.cat_name, b.brand_name
FROM goods g
JOIN category c ON g.cat_id = c.cat_id
JOIN brand b ON g.brand_id = b.brand_id
WHERE g.is_on_sale = 1
  AND g.is_delete = 0
  AND (g.goods_name LIKE '%手機%' OR g.keywords LIKE '%手機%')
  AND g.shop_price BETWEEN 1000 AND 5000
  AND g.cat_id IN (SELECT cat_id FROM category WHERE parent_id = 3)
GROUP BY g.goods_id
HAVING COUNT(DISTINCT g.attr_value_id) >= 2  -- 至少有 2 個規格屬性
ORDER BY g.sort_order ASC, g.goods_id DESC
LIMIT 20 OFFSET 0;

八、 避坑提示

  1. WHERE 中直接使用別名報錯:必須用子查詢/CTE 復用。
  2. 聚合函數誤用於 WHERE:WHERE COUNT(*) > 10 報錯,必須移至 HAVING。
  3. 隱式類型轉換導致索引失效:VARCHAR 列 = 數字,統一用字符串字面值。
  4. NOT IN 含 NULL 陷阱:WHERE col NOT IN (1,2,NULL) 永為 FALSE,改用 NOT EXISTS。
  5. OR 條件未全覆蓋索引導致全表掃描:拆分為 UNION ALL 或建組合索引。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved