74

是否有任何 SQL 子查询语法可以让您从字面上定义一个临时表?

例如,像

SELECT
  MAX(count) AS max,
  COUNT(*) AS count
FROM
  (
    (1 AS id, 7 AS count),
    (2, 6),
    (3, 13),
    (4, 12),
    (5, 9)
  ) AS mytable
  INNER JOIN someothertable ON someothertable.id=mytable.id

这将节省执行两三个查询:创建临时表,将数据放入其中,然后在连接中使用它。

我正在使用 MySQL,但会对其他可以做类似事情的数据库感兴趣。

4

8 回答 8

65

我想你可以用几个SELECTs 和UNIONs 来做一个子查询。

SELECT a, b, c, d
FROM (
    SELECT 1 AS a, 2 AS b, 3 AS c, 4 AS d
    UNION ALL 
    SELECT 5 , 6, 7, 8
) AS temp;
于 2009-06-12T06:44:23.570 回答
32

您可以在 PostgreSQL 中执行此操作:

=> select * from (values (1,7), (2,6), (3,13), (4,12), (5,9) ) x(id, count);
 id | count 
----+-------
  1 |     7
  2 |     6
  3 |    13
  4 |    12
  5 |     9

http://www.postgresql.org/docs/8.2/static/sql-values.html

于 2011-06-12T21:35:48.880 回答
22

在标准 SQL(SQL 2003 - 请参阅http://savage.net.au/SQL/)中,您可以使用:

INSERT INTO SomeTable(Id, Count) VALUES (1, 7), (2, 6), (3, 13), ...

通过更多的追逐,您还可以使用:

SELECT * FROM TABLE(VALUES (1,7), (2, 6), (3, 13), ...) AS SomeTable(Id, Count)

这些在 MySQL 中的工作是否是一个单独的问题 - 但您总是可以要求添加它,或者自己添加它(这就是开源的美妙之处)。

于 2009-06-12T07:02:47.440 回答
22

在 Microsoft T-SQL 2008 中,格式为:

SELECT a, b FROM (VALUES (1, 2), (3, 4), (5, 6), (7, 8), (9, 10) ) AS MyTable(a, b)

即上面提到的乔纳森,但没有'table'关键字。

看:

于 2013-06-03T22:36:13.463 回答
6

我找到了这个链接Temporary Tables With MySQL

CREATE TEMPORARY TABLE TempTable ( ID int, Name char(100) ) TYPE=HEAP; 

INSERT INTO TempTable VALUES( 1, "Foo bar" ); 

SELECT * FROM TempTable; 

DROP TABLE TempTable;
于 2009-06-12T06:49:25.260 回答
5

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

参见文档: MariaDBMySQL

玛丽亚数据库:

WITH literaltable (id,count) AS (VALUES (1,7),(2,6),(3,13),(4,12),(5,9))
SELECT MAX(count) AS max,COUNT(*) AS count FROM literaltable

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

SELECT 1 AS id,7 AS count UNION ALL VALUES (2,6),(3,13),(4,12),(5,9) ORDER BY count DESC

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

VALUES (1,7),(2,6),(3,13),(4,12),(5,9) ORDER BY 2 DESC

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

SELECT MAX(`7`) AS max,COUNT(*) AS count FROM (VALUES (1,7),(2,6),(3,13),(4,12),(5,9)) literaltable

MySQL:

我现在没有要测试的 MySQL v8.0.19 实例,但根据文档,这些中的任何一个都应该可以工作:

SELECT MAX(column_1) AS max,COUNT(*) AS count FROM (VALUES ROW(1,7), ROW(2,6), ROW(3,13), ROW(4,12), ROW(5,9)) literaltable

SELECT MAX(data) AS max,COUNT(*) AS count FROM (VALUES ROW(1,7), ROW(2,6), ROW(3,13), ROW(4,12), ROW(5,9)) literaltable(id,data)

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

我不确定,但这个开发工作日志页面似乎表明 MySQL 也实现了更短的语法(省略“ROW”,如 MariaDB),或者他们将在不久的将来实现。

于 2021-06-08T15:50:58.123 回答
1

一句话,是的。如果您的 SQL 产品支持公用表表达式 (CTE),则更好的 IMO 即比使用子查询更容易,而且可以多次使用相同的 CTE,例如,这可以在 SQL 中“创建”一个 0 到 999 之间唯一整数的序列表服务器 2005 及更高版本:

WITH Digits (nbr) AS 
(
 SELECT 0 AS nbr UNION ALL SELECT 1 UNION ALL SELECT 2 
 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 
 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 
 UNION ALL SELECT 9 
), 
Sequence (seq) AS
(
 SELECT Units.nbr + Tens.nbr + Hundreds.nbr 
   FROM Digits AS Units
        CROSS JOIN Digits AS Tens
        CROSS JOIN Digits AS Hundreds
)
SELECT S1.seq 
  FROM Sequence AS S1;

除非您实际上会对 Sequence 表做一些有用的事情,例如解析基表中 VARCHAR 列中的字符。

但是,如果您使用的是这个表,它只包含文字值、多次或多次查询,那么为什么不首先将它作为基表呢?我使用的每个数据库都有一个整数序列表(通常是 100K 行),因为它通常非常有用。

于 2009-06-12T09:07:05.427 回答
0

创建临时表(ID int,名称 char(100))选择 ....

阅读更多:http ://dev.mysql.com/doc/refman/5.0/en/create-table.html

(靠近底部)

这样做的好处是,如果在填充表格时出现任何问题(数据类型不匹配),表格将被自动删除。

早期的答案使用了 FROM SELECT 子句。如果可能的话,使用它,因为它可以省去清理桌子的麻烦。

FROM SELECT 的缺点(可能无关紧要)是创建的数据集有多大。临时表允许进行可能很关键的索引。用于后续查询。似乎违反直觉,但即使使用中等大小的数据集(约 1000 行),为查询操作创建索引也会更快。

于 2009-06-12T07:02:28.253 回答