tags:

views:

297

answers:

5

My purpose is: to get multiple rows from a value list,like (1,2,3,4,5),('a','b','c','anything') and so on.

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)

The above sql is surely ok,but my question is:is there a way to get the same result without

specifying a table?Because my purpose here is just to propagate rows by an id_set

another example:

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

mysql>

This example propagated a single row result without specifying a table,

but how to propagate multiple rows from a string like (1,2,3,4,5,6)?

+1  A: 

Something like this should work:

SELECT *
FROM (
    SELECT 0 as id
    UNION SELECT 1
    UNION SELECT 2
    UNION SELECT 3
    UNION SELECT 4
    UNION SELECT 5
)
Frank V
It feels quite loose,is there a more compact way to write this query?
Shore
Why the select *? The inner query alone should work well enough.
Stefan Mai
Short of utilizing an integers table like Alex Martelli suggests, this is as compact as you can get in a single query. You could create a temp table and use INSERT INTO ... VALUES ((1), (2), (3), (4), (5) (6)) or something like that, then SELECT FROM that temp table. It looks a little more compact, but functionally, there's more overhead.
eksortso
@Stefan: You are right, the outer select * isn't really needed. That is what came to my mind so I wrote it out quickly and posted it.
Frank V
@Shore: I don't know what you mean by "it feels quite loose". I do feel that this is the most compact way to write something like this. You could also get in to temp tables or a table reserved just for your purposes here (a table with a single column populated with integers) but that wouldn't be as compact (in my definition of compact).
Frank V
A: 

MySQL has a dummy table: DUAL. but using DUAL doesn't change anything (it's just for convenience), and certainly doesn't make this query work.

I'm sure there's a better way to achieve what you're trying to do. We might be able to help if you explain your problem.

Can Berk Güder
A: 

This does not answer your question exactly, but I believe this will fix your actual problem..

SET @counter = 0; SELECT (@counter := @counter + 1 as counter) ... rest of your query

Evert
my demo is using integer,but it's not limited to integer only,may also be string list like ('a','b','anything')
Shore
use a temporary table i guess then =)
Evert
Then this temporary table may accumulate to be a huge one,I'm afraid
Shore
Regardless it will have to reside in memory.. If you're afraid you'll run out of memory for this, you'll definitely have to assess your general approach because by the nature of your question it sounds like you have bigger problems to fix.
Evert
A: 

One technique I've found invaluable is an "integers table", which lets you easily do all kinds of neat things including this one (xaprb has written several blog posts on this technique and the closely related "mutex table" one).

Alex Martelli
I don't think it's stable since we need to clear the table each time after using,which may easily lead to fault.
Shore
@Shore, why do you need to clear your integers table after each use? If possible, you could make the table permanent and select from it as needed.
eksortso
seems that's the only way to propagate rows out of list,say,MUST with a table..
Shore
you can SELECT x FROM integers WHERE x BETWEEN 1 and 6 for example...
Alex Martelli
The pre-requisite is that the temporary table already has an entry there.And I'm afraid one day this table will become huge.
Shore
A: 

A simple and old fashioned way is to use a table which holds consecutive values.

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);

Once installed you can write queries as shown below.

get every second row:

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

get rows from 1101 to 1111:

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

So if you are in the need of greater ranges, then just increase the size of the consecutive values in table range10. Querying is simple, cost are low, no stored procedure or function needed.

Note:

You can create a table with consecutive char values, too. But varying the contents would not be so easy.

Tom Schaefer