是否有任何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,但对其他可以做类似事情的数据库感兴趣。
答案 0 :(得分:51)
我想您可以使用多个SELECT
和UNION
s进行子查询。
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;
答案 1 :(得分:23)
你可以在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
答案 2 :(得分:18)
在标准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工作是否是一个单独的问题 - 但你总是可以要求添加它,或者自己添加它(这是开源之美)。
答案 3 :(得分:14)
在Microsoft T-SQL 2008中,格式为:
SELECT a, b FROM (VALUES (1, 2), (3, 4), (5, 6), (7, 8), (9, 10) ) AS MyTable(a, b)
即。正如Jonathan上面提到的,但没有'table'关键字。
请参阅:
答案 4 :(得分: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;
答案 5 :(得分:1)
从 MariaDB v10.3.3 和 MySQL v8.0.19 开始,您现在可以完全做到这一点!
查看文档:{{3}}、MariaDB
MariaDB:
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
,因为 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 似乎表明 MySQL 也实现了较短的语法(省略了“ROW”,如 MariaDB),或者他们将在不久的将来实现。
答案 6 :(得分:0)
CREATE TEMPORARY TABLE(ID int,Name char(100))SELECT ....
阅读详情:http://dev.mysql.com/doc/refman/5.0/en/create-table.html
(靠近底部)
这样做的好处是,如果填充表格有任何问题(数据类型不匹配),表格将自动删除。
早期的答案使用了FROM SELECT子句。如果可能的话,使用它可以节省清理桌面的麻烦。
FROM SELECT的缺点(可能无关紧要)是创建数据集的大小。临时表允许索引,这可能是关键的。用于后续查询。看似违反直觉,但即使使用中等大小的数据集(~1000行),也可以更快地为查询创建索引。
答案 7 :(得分:0)
总之,是的。如果您的SQL产品支持公共表表达式(CTE),即使用子查询加上相同的CTE,则可以多次使用,例如更好的IMO。这是为了在SQL Server 2005及更高版本中“创建”0到999之间唯一整数的序列表:
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;
除了你实际上对序列表做了一些有用的事情,例如解析基表中VARCHAR列的字符。
但是,如果你使用的是这个只包含文字值,多次或多个查询的表,那么为什么不首先将它作为基表?我使用的每个数据库都有一个整数的Sequence表(通常是100K行),因为它通常非常有用。