2017-09-06 131 views
0

今天我開始嘗試在存儲過程中使用If Else語句。MySQL:存儲過程無法顯示正確的結果

這是我的查詢:

BEGIN 
    SELECT p.id, 
     p.content, 
     p.title, 
     t.id as type_id, 
     t.name as type_name, 
     c.id as category_id, 
     c.name as category_name, 
     s.id as status_id, 
     s.name as status_name, 
     u.id as user_id, 
     u.name as author, 
     u.username as username 
    FROM posts p 
    JOIN post_types t on t.id = p.type_id 
    JOIN categories c ON c.id = p.category_id 
    JOIN statuses s ON s.id = p.status_id 
    JOIN users u ON u.id = p.user_id 
    WHERE p.deleted_at IS NULL 
     AND p.user_id = user 
     AND p.type_id IN (IF(type='all', (SELECT id FROM post_types),(SELECT id FROM post_types WHERE name = type))) 
     AND p.created_at BETWEEN start_date and end_date 
    ORDER BY p.id DESC 
    LIMIT per_page 
    OFFSET skip; 
END 
在查詢我試圖選擇並加入一些表

,但問題是在哪裏聲明AND p.type_id IN (IF(type='all', (SELECT id FROM post_types),(SELECT id FROM post_types WHERE name = type)))

當我通過類型參數爲「所有」,存儲過程返回零值,但是當我將類型參數作爲'content'或'photo'傳遞時,它返回正確的值。 看來IN聲明無法讀取我的SELECT id FROM post_types查詢

任何人都可以糾正或給我參考如何做到這一點?

我寫錯了什麼? 感謝您的任何建議!

+0

嘗試使用'case when'而不是'If' –

回答

0

使用流量控制功能,如CASE()IF()當查詢返回多行,你會得到錯誤:

mysql> DROP TABLE IF EXISTS `post_types`, `posts`; 
Query OK, 0 rows affected (0.00 sec) 

mysql> CREATE TABLE IF NOT EXISTS `posts` (
    -> `id` SERIAL, 
    -> `type_id` BIGINT UNSIGNED NOT NULL 
    ->); 
Query OK, 0 rows affected (0.01 sec) 

mysql> CREATE TABLE IF NOT EXISTS `post_types` (
    -> `id` SERIAL, 
    -> `type` VARCHAR(7) NOT NULL 
    ->); 
Query OK, 0 rows affected (0.00 sec) 

mysql> INSERT INTO `post_types` 
    -> (`type`) 
    -> VALUES 
    -> ('content'), 
    -> ('photo'); 
Query OK, 2 rows affected (0.00 sec) 
Records: 2 Duplicates: 0 Warnings: 0 

mysql> INSERT INTO `posts` 
    -> (`type_id`) 
    -> VALUES 
    -> (1), 
    -> (2), 
    -> (2), 
    -> (1), 
    -> (2); 
Query OK, 5 rows affected (0.00 sec) 
Records: 5 Duplicates: 0 Warnings: 0 

mysql> SELECT 
    -> `id`, 
    -> `type_id` 
    -> FROM 
    -> `posts`; 
+----+---------+ 
| id | type_id | 
+----+---------+ 
| 1 |  1 | 
| 2 |  2 | 
| 3 |  2 | 
| 4 |  1 | 
| 5 |  2 | 
+----+---------+ 
5 rows in set (0.00 sec) 

mysql> SELECT 
    -> `id`, 
    -> `type` 
    -> FROM 
    -> `post_types`; 
+----+---------+ 
| id | type | 
+----+---------+ 
| 1 | content | 
| 2 | photo | 
+----+---------+ 
2 rows in set (0.00 sec) 

mysql> SET @`type` := 'all'; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SELECT 
    -> `id`, 
    -> `type_id` 
    -> FROM 
    -> `posts` 
    -> WHERE `type_id` IN (
    -> IF(@`type` = 'all', 
    ->  (SELECT `id` 
    ->  FROM `post_types`), 
    ->  (SELECT `id` 
    ->  FROM `post_types` 
    ->  WHERE `type` = @`type`) 
    -> ) 
    ->); 
ERROR 1242 (21000): Subquery returns more than 1 row 

13.2.10.5 Row Subqueriesdb-fiddle

可能的解決方法是重寫查詢:

mysql> SET @`type` := 'all'; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SELECT 
    -> `id`, 
    -> `type_id` 
    -> FROM 
    -> `posts` 
    -> WHERE `type_id` IN (
    -> SELECT 
    ->  `id` 
    -> FROM 
    ->  `post_types` 
    -> WHERE 
    ->  `type` = @`type` OR 
    ->  'all' = @`type` 
    ->); 
+----+---------+ 
| id | type_id | 
+----+---------+ 
| 1 |  1 | 
| 2 |  2 | 
| 3 |  2 | 
| 4 |  1 | 
| 5 |  2 | 
+----+---------+ 
5 rows in set (0.00 sec) 

mysql> SET @`type` := 'photo'; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SELECT 
    -> `id`, 
    -> `type_id` 
    -> FROM 
    -> `posts` 
    -> WHERE `type_id` IN (
    -> SELECT 
    ->  `id` 
    -> FROM 
    ->  `post_types` 
    -> WHERE 
    ->  `type` = @`type` OR 
    ->  'all' = @`type` 
    ->); 
+----+---------+ 
| id | type_id | 
+----+---------+ 
| 2 |  2 | 
| 3 |  2 | 
| 5 |  2 | 
+----+---------+ 
3 rows in set (0.01 sec) 

db-fiddle

0

這個問題剛剛解決了。 我正在使用這種方法。

BEGIN 
    SELECT p.id, 
     p.content, 
     p.title, 
     p.tags, 
     p.thumb, 
     p.is_commented, 
     p.slug, 
     p.created_at, 
     p.updated_at, 
     p.deleted_at, 
     t.id as type_id, 
     t.name as type_name, 
     c.id as category_id, 
     c.name as category_name, 
     s.id as status_id, 
     s.name as status_name, 
     u.id as user_id, 
     u.name as author, 
     u.username as username 
    FROM posts p 
    JOIN post_types t on t.id = p.type_id 
    JOIN categories c ON c.id = p.category_id 
    JOIN statuses s ON s.id = p.status_id 
    JOIN users u ON u.id = p.user_id 
    WHERE p.deleted_at IS NULL 
     AND p.user_id = user 
     AND CASE WHEN type = 'all' THEN p.type_id IN (SELECT id FROM post_types) ELSE p.type_id = (SELECT id FROM post_types WHERE name = type) END  
     AND p.created_at BETWEEN start_date and end_date 
    ORDER BY p.id DESC 
    LIMIT per_page 
    OFFSET skip; 
END 

打開任何建議。 Thankyou