【问题标题】:mysql fake selectmysql假选择
【发布时间】:2010-10-30 13:36:15
【问题描述】:

我的目的是:从一个值列表中获取多行,例如 (1,2,3,4,5),('a','b','c','anything') 等等。

mysql> select id from accounts where id in (1,2,3,4,5,6);
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  5 |
|  6 |
+----+
5 rows in set (0.00 sec)

上面的sql肯定没问题,但我的问题是:有没有办法在没有

的情况下得到同样的结果

指定一个表?因为我在这里的目的只是通过 id_set 传播行

另一个例子:

mysql> select now() as  column1;
+---------------------+
| column1             |
+---------------------+
| 2009-06-01 20:59:33 |
+---------------------+
1 row in set (0.00 sec)

mysql>

此示例在未指定表的情况下传播单行结果,

但是如何从 (1,2,3,4,5,6) 之类的字符串中传播多行?

【问题讨论】:

  • 什么行?行存在于表中。没有表格就没有行。
  • 我已经更新了我的问题,希望这次得到澄清:)

标签: mysql select


【解决方案1】:

这样的事情应该可以工作:

SELECT 0 as id
UNION SELECT 1
UNION SELECT 2
UNION SELECT 3
UNION SELECT 4
UNION SELECT 5

之后,你可以通过给它一个别名来从中选择你需要的东西:

SELECT *
FROM (
    SELECT 0 as id
    UNION SELECT 1
    UNION SELECT 2
    UNION SELECT 3
    UNION SELECT 4
    UNION SELECT 5
) `table1`

【讨论】:

  • 感觉很松散,有没有更简洁的方式来写这个查询?
  • 为什么选择 *?单独的内部查询应该足够好。
  • 没有像 Alex Martelli 所建议的那样使用整数表,这与您在单个查询中获得的一样紧凑。您可以创建一个临时表并使用 INSERT INTO ... VALUES ((1), (2), (3), (4), (5) (6)) 或类似的东西,然后从该临时表中选择。它看起来更紧凑一些,但在功能上,开销更大。
  • @Stefan:你是对的,外部 select * 并不是真正需要的。这就是我想到的,所以我迅速写出来并发布了它。
  • @Shore:我不知道您所说的“感觉很松散”是什么意思。我确实觉得这是写这样的东西的最紧凑的方式。您也可以在这里进入临时表或仅为您的目的保留的表(一个单列填充整数的表),但这不会那么紧凑(在我​​对紧凑的定义中)。
【解决方案2】:

MySQL 有一个虚拟表:DUAL。但是使用 DUAL 并没有改变任何东西(只是为了方便),而且肯定不会使这个查询工作。

我确信有更好的方法来实现您想要做的事情。如果您解释您的问题,我们或许可以提供帮助。

【讨论】:

  • 谢谢!我需要 DUAL 来选择带有 where 子句的常量值。选择性地插入常量是一种 hack。
【解决方案3】:

这并不能完全回答您的问题,但我相信这会解决您的实际问题..

SET @counter = 0; SELECT (@counter := @counter + 1 as counter) ...其余的查询

【讨论】:

  • 我的demo使用的是整数,但不仅限于整数,也可以是字符串列表,如('a','b','anything')
  • 使用临时表我猜然后 =)
  • 那么这个临时表可能会累积成一个巨大的,恐怕
  • 不管它必须驻留在内存中.. 如果你担心你会为此耗尽内存,你肯定必须评估你的一般方法,因为根据你的问题的性质听起来你有更大的问题要解决。
【解决方案4】:

我发现一种非常有价值的技术是an "integers table",它可以让你轻松地做各种巧妙的事情,包括这个(xaprb 已经写了几篇关于这种技术的博客文章和密切相关的“互斥表”)。

【讨论】:

  • 我觉得不太稳定,每次用完都要清表,容易出故障。
  • @Shore,为什么每次使用后都需要清除整数表?如果可能,您可以将表设为永久并根据需要从中进行选择。
  • 前提是临时表里面已经有条目了,而且恐怕有一天这张表会变大。
【解决方案5】:

一种简单而老式的方法是使用一个包含连续值的表。

DROP TABLE IF EXISTS `range10`;
CREATE TABLE IF NOT EXISTS `range10` (
  `id` int(11) NOT NULL,
  KEY `id` (`id`)
) ENGINE=MyISAM;
INSERT INTO `range10` (`id`) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);

安装后,您可以编写如下所示的查询。

每隔一行获取一次:

select * from your_data_table where id in (
 SELECT id*2 as id FROM `range10` WHERE id in(
  select id from `range10`
 )
)

获取从 1101 到 1111 的行:

select * from your_data_table where id in (
 SELECT id+1100 as id FROM `range10` WHERE id in(
  select id from `range10`
 )
)

因此,如果您需要更大的范围,则只需增加表 range10 中连续值的大小。 查询简单,成本低,无需存储过程或函数。

注意:

您也可以创建具有连续字符值的表。但是改变内容并不是那么容易。

【讨论】:

    【解决方案6】:

    这是一种直接使用 MySQL 请求 SELECT 创建自定义行的方法:

    SELECT ALL *
    FROM (
        VALUES
            ROW ('1.1', '1.2', '1.3'),
            ROW ('2.1', '2.2', '2.3'),
            ROW ('3.1', '3.2', '3.3')
    ) AS dummy (c1, c2, c3)
    

    给我们一张桌子dummy

    c1   c2   c3
    -------------
    1.1  1.2  1.3
    2.1  2.2  2.3
    3.1  3.2  3.3
    

    【讨论】:

      猜你喜欢
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 2013-05-15
      • 2015-11-11
      • 2012-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多