你能定义“字面意思”吗? SQL 中的表?

发布于 2024-07-24 08:30:53 字数 377 浏览 9 评论 0原文

是否有任何 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,但对其他可以做类似事情的数据库感兴趣。

Is there any SQL subquery syntax that lets you define, literally, a temporary table?

For example, something like

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

This would save having to do two or three queries: creating temporary table, putting data in it, then using it in a join.

I am using MySQL but would be interested in other databases that could do something like that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

梦魇绽荼蘼 2024-07-31 08:30:53

我想您可以使用多个 SELECTUNION 组合来执行子查询。

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;

I suppose you could do a subquery with several SELECTs combined with 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;
美男兮 2024-07-31 08:30:53

您可以在 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

You can do it in 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

梨涡 2024-07-31 08:30:53

在 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”关键字。

请参阅:

In Microsoft T-SQL 2008 the format is:

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

I.e. as Jonathan mentioned above, but without the 'table' keyword.

See:

叹倦 2024-07-31 08:30:53

在标准 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 中是否工作是一个单独的问题 - 但您总是可以要求添加它,或者自己添加它(这就是开源的美妙之处)。

In standard SQL (SQL 2003 - see http://savage.net.au/SQL/) you can use:

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

With a bit more chasing, you can also use:

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

Whether these work in MySQL is a separate issue - but you can always ask to get it added, or add it yourself (that's the beauty of Open Source).

风和你 2024-07-31 08:30:53

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

请参阅文档:MariaDBMySQL

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还实现了更短的语法(省略“ROW”,如 MariaDB),或者他们将在不久的将来实现。

Since MariaDB v10.3.3 and MySQL v8.0.19 you can now do exactly that!

See docs: MariaDB, MySQL

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

I used a WITH here because MariaDB doesn't supply nice column names for VALUES .... You can use it in a union without column names:

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

And although the docs don't appear to mention it, you can even use it as a top-level query:

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

The actual column names are in fact the just first row of values, so you can even do this (though it's inelegant, and you can run into duplicate column name errors):

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

MySQL:

I don't have an instance of MySQL v8.0.19 to test against right now, but according to the docs either of these should work:

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)

Unlike MariaDB, MySQL supplies automatic column names column_0, column_1, column_2, etc., and also supports renaming all of a subquery's columns when referencing it.

I'm not sure, but this dev worklog page seems to suggest that MySQL has also implemented the shorter sytax (omitting "ROW", like MariaDB), or that they will in the near future.

北斗星光 2024-07-31 08:30:53

我找到了这个链接 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;

I found this link 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;
酒浓于脸红 2024-07-31 08:30:53

总之,是的。 在我看来,如果您的 SQL 产品支持通用表表达式 (CTE),即比使用子查询更容易看懂,而且相同的 CTE 可以多次使用,例如,这可以在 SQL 中“创建”一个由 0 到 999 之间的唯一整数组成的序列表,那就更好了Server 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;

除非您实际上对序列表执行一些有用的操作,例如解析基表中 VARCHAR 列中的字符。

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

In a word, yes. Even better IMO if your SQL product supports common table expressions (CTEs) i.e. easier on the eye than using a subquery plus the same CTE can be used multiple times e.g. this to 'create' a sequence table of unique integers between 0 and 999 in SQL Server 2005 and above:

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;

except you'd actually do something useful with the Sequence table e.g. parse the characters from a VARCHAR column in a base table.

HOWEVER, if you are using this table, which consists only of literal values, multiple time or in multiple queries then why not make it a base table in the first place? Every database I use has a Sequence table of integers (usually 100K rows) because it is so useful generally.

墟烟 2024-07-31 08:30:53

创建临时表 ( ID int, Name char(100) ) SELECT ....

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

(靠近底部)

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

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

FROM SELECT 的缺点(可能并不重要)是创建的数据集有多大。 临时表允许建立索引,这可能是至关重要的。 以便后续查询。 似乎违反直觉,但即使对于中等大小的数据集(约 1000 行),为查询操作创建索引也会更快。

CREATE TEMPORARY TABLE ( ID int, Name char(100) ) SELECT ....

Read more at : http://dev.mysql.com/doc/refman/5.0/en/create-table.html

( near the bottom )

This has the advantage that if there is any problem populating the table ( data type mismatch ) the table is automatically dropped.

An early answer used a FROM SELECT clause. If possible use that because it saves the headache of cleaning up the table.

Disadvantage ( which may not matter ) with the FROM SELECT is how large is the data set created. A temporary table allows for indexing which may be critical. For the subsequent query. Seems counter-intuitive but even with a medium size data set ( ~1000 rows), it can be faster to have a index created for the query to operate on.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文