Mysql:在选择语句中创建内联表?

16

在MySql中是否有一种方法可以创建内联表并用于连接操作?

类似于:

SELECT LONG [1,2,3] as ID, VARCHAR(1) ['a','b','c'] as CONTENT

这将输出

|  ID  |  CONTENT  |
| LONG | VARCHAR(1)|
+------+-----------+
|   1  |    'a'    |
|   2  |    'b'    |
|   3  |    'c'    |

我可以在类似这样的连接中使用:

SELECT 
  MyTable.*,
  MyInlineTable.CONTENT
FROM
  MyTable
  JOIN 
    (SELECT LONG [1,2,3] as ID, VARCHAR(1) ['a','b','c'] as CONTENT MyInlineTable)
  ON MyTable.ID = MyInlineTable.ID

我意识到可以这样做

SELECT 1,'a' UNION SELECT 2,'b' UNION SELECT 3,'c'

但那似乎相当恶劣。

我不想使用存储过程,因为potentially a、b、c可以在每个查询中都会变化,数据的大小也会随之改变。此外,存储过程需要保存在数据库中,而我不想仅仅为此修改数据库。视图也是一样。

我真正要找的是一个更好语法的 SELECT 1,'a' UNION SELECT 2,'b' UNION SELECT 3,'c'


这似乎是一个简单明了的概念,具有明显的用例。我也需要找到类似的东西。 - Landon Kuhn
你找到任何解决方案了吗?我很好奇。 - Fernando Carvalhosa
@FernandoCarvalhosa:不行,看起来没有联合就做不到。 - edeboursetty
@d--b 临时表没有用处吗?顺便问一下,为什么你觉得使用 union 看起来很糟糕?性能问题吗? - Fernando Carvalhosa
我更新了我的答案,并加入了一些使用临时表的代码。还没有测试,今晚会测试一下。 - Fernando Carvalhosa
刚刚测试了一下,它可以正常工作。使用临时表比使用 UNION 更容易添加数据。在关闭连接后,临时表将被删除。建议您有时间时查看一下。 - Fernando Carvalhosa
3个回答

7
我现在能想到的方法只有使用UNION或创建一个TEMPORARY TABLE,并将这些值插入其中。这种方法适合你吗?

TEMPORARY TABLE(已测试可行):

创建:

CREATE TEMPORARY TABLE MyInlineTable (id LONG, content VARCHAR(1) );

INSERT INTO MyInlineTable VALUES
(1, 'a'),
(2, 'b'),
(3, 'c');

用法:

SELECT 
  MyTable.*,
  MyInlineTable.CONTENT
FROM
  MyTable
  JOIN 
    SELECT * FROM MyInlineTable;
  ON MyTable.ID = MyInlineTable.ID

TEMPORARY_TABLES lifetime (参考):

自动删除临时表,除非已经使用 DROP TABLE 显式地删除,然后再超出作用域。

.

所有其他本地临时表都会在当前会话结束时自动删除。

.

全局临时表会在创建该表的会话结束并且所有其他任务停止引用它们时自动删除。任务和表之间的关联仅保持一个单个 Transact-SQL 语句的生命周期。这意味着,在创建会话结束时最后一个活动引用表的 Transact-SQL 语句完成后,将删除全局临时表。


7
我希望您能翻译以下的内容:

我真正需要的是一个更好的语法来执行 SELECT 1,'a' UNION SELECT 2,'b' UNION SELECT 3,'c'。

MySQL 8.0.19中引入了行构造器,可以用它实现。

VALUES ROW (1,'a'), ROW(2,'b'), ROW(3,'c') 

并且使用JOIN:

SELECT *
FROM tab 
JOIN (VALUES ROW (1,'a'), ROW(2,'b'), ROW(3,'c') ) sub(id, content)
  ON tab.id = sub.id;

db<>fiddle演示


除了第一列不被命名为 id 之外,“从 VALUES 输出的表的列具有隐式命名的列 column_0、column_1、column_2 等,始终以 0 开头。” - Bill Karwin
1
@BillKarwin,你可以随意命名列名:SELECT * FROM (VALUES ROW(1, 'a'), ROW(2, 'b')) foo(foo_id, foo_content); - Jalal
@Jalal,谢谢你,文档中这一点对我来说不太清楚。 - Bill Karwin

-1

这对我来说似乎是一种过于繁重的解决方案...(请参见问题中的编辑) - edeboursetty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接