【问题标题】:Return default value for non-existing rows返回不存在行的默认值
【发布时间】:2014-03-01 17:05:08
【问题描述】:

到最基本的查询

SELECT id, column1, column2
FROM table1
WHERE id IN ("id1", "id2", "id3")

其中 where 语句中的参数作为变量传递,我还需要为不存在 id 的行返回值。一般来说,这是一个非常相似的问题,如下所述:SQL: How to return an non-existing row? 但是,WHERE 语句中有多个参数

id2不存在时的结果:

-------------------------------
| id  | column1   | column2   |
-------------------------------
| id1 | some text | some text |
| id3 | some text | some text |
-------------------------------

id2 不存在时的期望结果

-----------------------------------
| id  | column1     | column2     |
-----------------------------------
| id1 | some text   | some text   |
| id2 | placeholder | placeholder |
| id3 | some text   | some text   |
-----------------------------------

我的第一个想法是创建一个临时表并将其连接到查询中。不幸的是,我无权创建任何类型的临时表,因此我只能使用 SELECT 语句。

有没有办法在 SQL SELECT 查询中做到这一点?

编辑: 确实,上述是一种假设情况。在 WHERE 子句中可以是数百个 id,其中缺失的数量未知。

【问题讨论】:

标签: mysql sql


【解决方案1】:

你可以做一个派生表来创建一个类似临时表的东西,但它只能用于这个查询:

SELECT t.id, COALESCE(t.column1, _dflt.column1) AS column1
FROM (
  SELECT 'id1' AS id, 'placeholder text 1' as column1
  UNION ALL
  SELECT 'id2', 'placeholder text 3'
  UNION ALL
  SELECT 'id3', 'placeholder text 3'
) AS _dflt
LEFT OUTER JOIN table1 t USING (id);

回复:

我刚刚在 MySQL 5.6.15 上测试了上面的方法,看看我可以通过一系列 UNION ALL 获得多少不同的 SELECT,每个 SELECT 一行。

我让派生表返回 5332 行,但我认为如果我有更多 RAM,我可以做得更高。

如果我再试一次 UNION ALL,我会得到:ERROR 1064 (42000): memory exhausted near '' at line 10665。我在这个 VM 上只配置了 2.0GB 的 RAM。

无论有多少个 id 未知,此解决方案都能正常工作。只需将它们全部放在派生表中即可。通过使用LEFT OUTER JOIN,它会自动找到那些存在于您的table1 中的那些,并且对于那些缺失的那些,派生表中的条目将与NULL 匹配。

COALESCE() 函数返回其第一个非空参数,因此如果存在匹配行,它将使用匹配行中的列。如果没有找到,它将默认为派生表中的列。

【讨论】:

  • 嘿,这不是通用解决方案,我想 OP 是在谈论有一百个 id 的假设情况,其中一半丢失了。
  • 谢谢。实际上,将不胜感激通用解决方案。以上是假设情况。在 WHERE 子句中可以是数百个 id,其中缺失的数量未知。
【解决方案2】:

创建一个将 id1、id2 等作为输入的存储过程...

DELIMITER //
CREATE PROCEDURE P1(IN p_in varchar(5))
BEGIN
DECLARE count integer;
SELECT count(id) INTO count FROM TABLE1 
WHERE id = p_in;

IF count = 1 THEN
    SELECT * from table1 where id = p_in;
ELSE
    select p_id, 'some text', 'some text';
END IF;
END//

DELIMITER ;

调用过程以获得所需的输出..

CALL P1('id1'); 
CALL P2('id2'); 

.. 等等你的程序..

【讨论】:

    【解决方案3】:

    投影一个包含你想要的所有候选 id 的派生表,然后左连接到它:

    选择 ids.id, coalesce(table1.column1,'placeholder') 从 (选择 'id1' 作为 id 联盟 选择“id2” 联盟 选择 'id3') id 左连接表1 在 ids.id1 = table1.id1 和 (...) 中的 table1.id;

    如果您从外部源(例如应用程序)生成候选 ids 列表,您可以将 id 插入到 temporary table 中,然后加入它(MySql 尚不支持表变量)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-27
      • 1970-01-01
      • 1970-01-01
      • 2012-11-03
      • 2019-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多