【问题标题】:subquery: is it good practise to use having clause to filter out rows of outer query that contains subquery's null values子查询:使用having子句过滤掉包含子查询空值的外部查询行是一种好习惯吗
【发布时间】:2021-08-17 16:07:03
【问题描述】:

我有以下表格:

SELECT * FROM medicine

| id | name        | producer |
+----+-------------+----------+
|  1 | aspirin     | pharma   |
|  2 | cetamol     | tamiko   |
|  3 | brufen      | pharma   |
|  4 | cetacodeine | adamco   |
|  5 | actifed     | tamiko   |
|  6 | claritin    | tamiko   |
+----+-------------+----------+

SELECT * FROM liquid

+-----+------+-------+
| lid | m_id | price |
+-----+------+-------+
| l1  |    2 |  1000 |
| l2  |    3 |  1500 |
| l3  |    4 |  3000 |
| l4  |    5 |  2000 |
| l5  |    6 |  1800 |
+-----+------+-------+

SELECT * FROM tablet

+-----+------+-------+
| tid | m_id | price |
+-----+------+-------+
| t1  |    1 |   900 |
| t2  |    2 |   600 |
| t3  |    3 |  1200 |
| t4  |    5 |  2000 |
+-----+------+-------+

其中最后两个表中的 m_id 具有引用第一个表中的 id 的外键。

我正在尝试列出仅由生产商 tamiko 生产的液态药物的 lid 和 name 执行以下语句将导致包含从子查询返回的空值的行,我想省略

SELECT lid, (SELECT name FROM medicine WHERE liquid.m_id=medicine.id AND medicine.producer='tamiko') AS byTamiko FROM liquid;

+-----+----------+
| lid | byTamiko |
+-----+----------+
| l1  | cetamol  |                                                                                 
| l2  | NULL     |                                                                                 
| l3  | NULL     |                                                                                  
| l4  | actifed  |                                                                                 
| l5  | claritin |                                                                                
+-----+----------+

所以我做了一些尝试,使用HAVING 子句似乎是一个解决方案

SELECT lid, (SELECT name FROM medicine WHERE liquid.m_id=medicine.id AND medicine.producer='tamiko') AS byTamiko FROM liquid HAVING byTamiko IS NOT NULL;

| lid | byTamiko |
+-----+----------+
| l1  | cetamol  |
| l4  | actifed  |
| l5  | claritin |
+-----+----------+

但是,我的老师不同意 HAVING 子句只能与聚合函数和 GROUP BY 语句一起使用。我现在很困惑这是否是适当的用法?究竟发生了什么使它起作用?

注意:我必须只使用子查询而不是任何JOIN 或其他语句来执行此查询。

注意2:请注意,这不是重复的,我试图解释它是如何工作的,以及它是否正确使用。

【问题讨论】:

  • 实际上,您的子查询应该替换为JOIN 运行一次,而不是针对外部表的每一行。如果您正在运行子查询以进行学习练习,请忽略此建议
  • @Parfait 是的,我运行它是为了学习。

标签: mysql sql subquery filtering having-clause


【解决方案1】:

确实不太合适。

在 SQL 标准中,having 定义为在聚合之后进行过滤,where 用于在聚合之前进行过滤(如果有任何聚合)。

MySQL 对此进行了扩展以允许 having 在非聚合查询中使用。此扩展允许您在不使用子查询的情况下过滤列别名。但是你应该在聚合之前使用where 进行过滤。

【讨论】:

    【解决方案2】:

    所以它应该是这样的?

    SELECT lid, (
        SELECT name 
        FROM medicine 
        WHERE liquid.m_id=medicine.id AND medicine.producer='tamiko'
    ) AS byTamiko 
    FROM liquid 
    WHERE byTamiko IS NOT NULL;
    
    

    【讨论】:

    • 这是一个问题还是一个答案?
    • 你试过了吗?您不能使用 WHERE 子句过滤别名
    猜你喜欢
    • 2010-12-24
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多