MySQL:存储过程没有显示正确的结果

时间:2017-09-06 04:42:28

标签: mysql stored-procedures

今天我开始尝试在商店程序中使用If Else语句。

这是我的疑问:

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

在该查询中我尝试选择并加入一些表,但问题出在Where语句AND p.type_id IN (IF(type='all', (SELECT id FROM post_types),(SELECT id FROM post_types WHERE name = type)))

当我将类型参数传递为' all'时,存储过程返回零值,但是当我将类型参数传递为' content'或者'照片',它会返回正确的值。 似乎IN语句无法读取我的SELECT id FROM post_types查询

任何人都可以纠正或给我参考如何做到这一点?

我写错了吗? 谢谢你的建议!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

打开任何建议。三江源