【问题标题】:MySQL: Select from coma separated list / list as table? "SELECT a FROM (1, 2, 3)"MySQL:从逗号分隔列表/列表中选择表? “从(1、2、3)中选择一个”
【发布时间】:2012-11-03 21:58:12
【问题描述】:

有没有可能做这样的事情(显然这个语法行不通):

SELECT a FROM (1, 2, 3)

得到这个:

| a |
+---+
| 1 |
| 2 |
| 3 |

?

那是我想从逗号分隔列表中创建行,而不使用任何表,或者至少不在 db 中创建表(也许这可以使用临时表之类的东西?)。

也许可以在不使用 select 的情况下获取给定值的列,即使用其他一些 sql 语句?如果这在 MySQL 中是不可能的,但在其他一些 SQL 中是可能的,那么它仍然会很有趣。

【问题讨论】:

  • @SashiKant 其他 1000 人也不能...

标签: mysql sql select


【解决方案1】:
SELECT 1 a UNION ALL SELECT 2 a UNION ALL SELECT 3 a;

【讨论】:

  • 非常甜蜜,好主意,虽然陈述有点长:) 但我相信你很可能有一个被接受的答案! :)
  • @aykut :因为你没有消除任何重复我建议使用UNION ALL 而不是UNION
  • @morphles,你能给出一个你想要的场景吗?我没有弄清楚你的问题:/
  • 我使用应用程序,它有多种语言的文本,我们没有前端来输入一些文本。所以我像这样插入它们(默认情况下,所有语言的开始文本都是相同的): INSERT INTO translations (name, translation, lang_id) SELECT 'somename','some_trans',id FROM languages。有了这样的选择,我应该能够在一个查询中为多个名称添加连接和插入翻译。诚然,这是一个蹩脚的用例,但我敢打赌,我会找到更有效的用途,因为我有办法做到这一点。诚然,我自己无法找到解决方案,这对我来说有点失败:)
  • 您想用现有语言的文本填充所有缺少的语言翻译文本吗?是一次性工作吗?如果是的话,我想你可以在你的应用层做到这一点。
【解决方案2】:

可以选择临时表吗?然后我会有一个建议,诚然,它有超过 1 个查询:

-- DROP TEMPORARY TABLE tmp_list IF EXISTS;
CREATE TEMPORARY TABLE tmp_list (a INT);
INSERT INTO tmp_list (a) VALUES (1), (2), (3);
SELECT a FROM tmp_list;

【讨论】:

    【解决方案3】:

    如果这在 MySQL 中是不可能的,但在其他一些 SQL 中是可能的,那么知道它仍然会很有趣。

    在标准 SQL 中是这样的

    select *
    from ( values (1), (2), (3) ) t
    

    这至少在 PostgreSQL 和 DB2 中有效。

    在 PostgreSQL 中,您可以通过扩展别名来为列命名(不确定该列别名是否是 SQL 标准的一部分)。

    select *
    from ( values (1), (2), (3) ) t (id)
    

    以下是使用公用表表达式的上述替代方法。

    with my_values (id) as (
      values (1), (2), (3)
    )
    select *
    from my_values;
    

    【讨论】:

      【解决方案4】:

      从 MariaDB v10.3.3 和 MySQL v8.0.19 开始,您现在可以完全做到这一点!

      请参阅文档:MariaDB、MySQL

      MariaDB:

      WITH mylist (a) AS (VALUES (1),(2),(3))
      SELECT a FROM mylist
      

      我在这里使用了WITH,因为 MariaDB 没有为VALUES ... 提供好的列名。您可以在没有列名的联合中使用它:

      SELECT 1 AS a UNION ALL VALUES (2),(3)
      

      虽然文档似乎没有提到它,但您甚至可以将其用作顶级查询:

      VALUES (1),(2),(3) ORDER BY 1 DESC
      

      实际的列名实际上只是第一行值,所以你甚至可以这样做(虽然它不优雅,而且你可能会遇到重复的列名错误):

      SELECT `4` AS a FROM (VALUES (4),(5),(6)) mylist
      

      MySQL:

      我现在没有要测试的 MySQL v8.0.19 实例,但根据文档 [编辑:使用 dbfiddle.uk 在 MySQL v8.0.23 上成功测试,请参阅评论 #2 中的链接] 这些中的任何一个都应该有效:

      SELECT column_0 AS a FROM (VALUES ROW(1), ROW(2), ROW(3)) mylist
      
      SELECT a FROM (VALUES ROW(1), ROW(2), ROW(3)) mylist(a)
      

      与 MariaDB 不同,MySQL 提供自动列名 column_0、column_1、column_2 等,并且还支持在引用子查询时重命名子查询的所有列。

      我不确定,但this dev worklog page 似乎暗示 MySQL 也已实现 [编辑:尚未实现,截至 v8.0.26] 较短语法(省略“ROW”,如 MariaDB),或者它们可能在不久的将来的某个时间点。

      【讨论】:

      • 您提供的解决方案均不适用于 MySQL
      • @dnetix 我不敢苟同:dbfiddle.uk/… 和 dbfiddle.uk/… 你确定你在 v8.0.19+ 上测试过吗?
      • 使用 5.7.23 MySQL Community Server (GPL) 每个命令都响应“ERROR 1064 (42000): You have an error in your SQL syntax; ...”临时表进行连接,这是一个较短的列表,原来是 1000 bines 来检查 CREATE TEMPORARY TABLE tmp_list (bin varchar(6)); INSERT INTO tmp_list (bin) VALUES ('365454'), ('360218'), ('360218'), ('364172'), ('364173'), ('364172'); SELECT bin, name FROM tmp_list LEFT JOIN provider_bin ON provider_bin.bine = tmp_list.bin WHERE provider_bin.bine 不为空;删除临时表 tmp_list;
      • @dnetix 这个答案的第一行明确指出:“由于 MariaDB v10.3.3 和 MySQL v8.0.19 你现在可以做......”。由于您仅使用 MySQL 的 v5.7.23,因此此答案不适用于您的设置,因此您遇到的错误完全可以预料。当答案明确指出它不适用于您使用的 MySQL 版本时,请不要投反对票或发布误导性的一般 cmets,例如“它不起作用”!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      • 2012-06-29
      • 1970-01-01
      • 1970-01-01
      • 2015-11-03
      • 2016-12-28
      • 2013-03-06
      相关资源
      最近更新 更多