what is mysql query to print 1 to 10? - mysql

I know there is sql query to print count from 1 to 10 as below:
select rownum from dual where rownum<=10;
In the same way i am trying in the mysql but it is throwing error "Unknown column rownum in field list". So, It would be great if anyone provide me the mysql query to perform the same operation. Thanks in advance.

In MySQL 8+ you can use a recursive CTE to do this:
WITH RECURSIVE cte AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM cte WHERE n < 10
)
SELECT n FROM cte
Output:
n
1
2
3
4
5
6
7
8
9
10
Demo on dbfiddle

There is no straightforward way to do this in MySQL.
MySQL does not fully support the DUAL table. It can be used as a placeholder table in certain queries which do not require a table, but it does not have the same behavior as the DUAL table in other database servers -- it will only ever return one row, even if more rows are requested:
mysql> SELECT ROW_NUMBER() OVER() FROM DUAL LIMIT 10;
+---------------------+
| row_number() over() |
+---------------------+
| 1 |
+---------------------+
mysql> SELECT ROW_NUMBER() OVER() FROM DUAL WHERE ROW_NUMBER() OVER() < 10;
ERROR 3593 (HY000): You cannot use the window function 'row_number' in this context.'
(Yes, there's really a stray apostrophe at the end of that error message.)
There is one really dumb way of creating a sequence:
mysql> SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5;
+---+
| 1 |
+---+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+---+
5 rows in set (0.00 sec)
Obviously, this gets unwieldy for large sequences, but it's about the best you'll get in stock MySQL. (Some of the forks, like MariaDB, have some features which can be used for this.)

Using the table function (the method for creating a temporary table only for the current query): like numbers function which will print 1 to 10:
SELECT * FROM numbers(1, 10);

By using below query you can get 1 to 10.
Sequence of 10 numbers
select * from (select 1 x union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 10) A
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=1f8b71c1fef4b8e0350f2b28eb15c3be

Related

way to populate number of rows in mysql without selecting table

I am looking for a way to populate values in row in mysql
for example if i execute query
select 1,2,3,4
it gives response
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
| 1 | 2 | 3 | 4 |
+---+---+---+---+
that is in row
is there a possible way to produce this data in column
like
1
2
3
4
With the introduction of Recursive with clause in MySQL version 8.0 or higher, We now have a row generator in MySQL -
WITH RECURSIVE cte_count (n)
AS (
SELECT 1
UNION ALL
SELECT n + 1
FROM cte_count
WHERE n < 100
)
SELECT n
FROM cte_count;
Before version 8.0 MySQL doesn't have any inbuilt row_generator functionality.
If you want values in a column, you can use:
select 1 as n union all
select 2 as n union all
select 3 as n union all
select 4 as n
This construct is often used in derived tables (or more recently in CTEs).
If you just need a set number of values, then an existing table (that is big enough) can be used:
select (#rn := #rn + 1) as n
from t cross join
(select #rn := 0) params
limit 4;

MySQL: Get count of data in comma separated column [duplicate]

This question already has answers here:
Search with comma-separated value mysql
(1 answer)
MySql PHP select count of distinct values from comma separated data (tags)
(5 answers)
Closed 4 years ago.
I have a table that stores data like:
userid books
ym0001 dictionary,textbooks,notebooks
ym0002 textbooks,dictionary
I want to count number of times each book occurs. I want my result to be in this format.
books Counts
dictionary 2
notebooks 1
textbooks 2
This is mysql. Please help
The following approach builds a result of 1000 integers, then uses those integers (n) to locate segments within the comma seperated string, and for each segment it creates a new row so that the derived table looks like this:
userid | book
:----- | :---------
ym0001 | dictionary
ym0002 | textbooks
ym0001 | textbooks
ym0002 | dictionary
ym0001 | notebooks
Once that exists it is a simple matter of grouping by book to arrive at the counts.
select
book, count(*) Counts
from (
select
t.userid
, SUBSTRING_INDEX(SUBSTRING_INDEX(t.books, ',', numbers.n), ',', -1) book
from (
select #rownum:=#rownum+1 AS n
from
(
select 0 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
) a
cross join (
select 0 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
) b
cross join (
select 0 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
) c
cross join (select #rownum:=0) r
) numbers
inner join mytable t
on CHAR_LENGTH(t.books)
-CHAR_LENGTH(REPLACE(t.books, ',', '')) >= numbers.n-1
) d
group by
book
order by
book
book | Counts
:--------- | -----:
dictionary | 2
notebooks | 1
textbooks | 2
If you already have a table of numbers, use that instead.
the cross joins of a b and c dynamically produce 1000 rows, if you need more add further cross joins similar to c. i.e. the number of numbers should exceed the maximum length of your comma seperated data
db<>fiddle here

SELECT on an array of constants

In MySQL, how is it possible to do a SELECT on an array of constant values? Something similar to this:
SELECT ['1', '2', '3'] AS ID;
Where the desired output is:
+-----+
| ID |
+-----+
| 1 |
| 2 |
| 3 |
You can use joins to generate a series of rows.
SELECT 1 AS ID UNION SELECT 2 UNION SELECT 3
For small amounts of data this works well. Down side is that there is no index to check these on.
A temp table is likely far better for this as at least any SQL that joins against these values can then use indexes.
Another possibility if the values are from a limited pool is to just have a table which contains all possible values and select from it:-
SELECT ID
FROM all_poss_values
WHERE ID IN (1,2,3)
or using a generated range of values (which again loses the availability of indexes):-
SELECT 1 + units.i + tens.i * 10 AS ID
FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units,
(SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
WHERE 1 + units.i + tens.i * 10 IN (1,2,3)

SQL split comma separated row [duplicate]

This question already has answers here:
MySQL: Split comma separated list into multiple rows
(4 answers)
Closed 9 years ago.
I have a column with a variable number of comma seperated values:
somethingA,somethingB,somethingC
somethingElseA, somethingElseB
And I want the result to take each value, and create a row:
somethingA
somethingB
somethingC
somethingElseA
somethingElseB
How can I do this in SQL (MySQL)?
(I've tried googling "implode" and "lateral view", but those don't seem to turn up related questions. All the related SO questions are trying to do much more complicated things)
You can do it with pure SQL like this
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.values, ',', n.n), ',', -1) value
FROM table1 t CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N 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) a
,(SELECT 0 AS N 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) b
ORDER BY n
) n
WHERE n.n <= 1 + (LENGTH(t.values) - LENGTH(REPLACE(t.values, ',', '')))
ORDER BY value
Note: The trick is to leverage tally(numbers) table and a very handy in this case MySQL function SUBSTRING_INDEX(). If you do a lot of such queries (splitting) then you might consider to populate and use a persisted tally table instead of generating it on fly with a subquery like in this example. The subquery in this example generates a sequence of numbers from 1 to 100 effectively allowing you split up to 100 delimited values per row in source table. If you need more or less you can easily adjust it.
Output:
| VALUE |
|----------------|
| somethingA |
| somethingB |
| somethingC |
| somethingElseA |
| somethingElseB |
Here is SQLFiddle demo
This is how the query might look with a persisted tally table
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.values, ',', n.n), ',', -1) value
FROM table1 t CROSS JOIN tally n
WHERE n.n <= 1 + (LENGTH(t.values) - LENGTH(REPLACE(t.values, ',', '')))
ORDER BY value
Here is SQLFiddle demo

MySQL Binary Tree Index order

I have a query like this:
SELECT * FROM mytable WHERE
((num=8198747 AND class='A') OR
(num=1646463 AND class='B') OR
(num=4099442 AND class='C') OR
(num=1176312 AND class='A') OR
(num=2146847 AND class='B') OR
(num=7000296 AND class='F') OR
--...about 400 more clauses like this
)
SHOW INDEXES FROM mytable;
+---------+------------+----------+--------------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name |
+---------+------------+----------+--------------+---------------+
| mytable | 0 | PRIMARY | 1 | id |
| mytable | 1 | nc_idx | 1 | num |
| mytable | 1 | nc_idx | 2 | class |
+---------+------------+----------+--------------+---------------+
3 rows in set (0.00 sec)
My understanding is that for each of the ~400 clauses in the query, it will do a separate BTREE lookup on num=XXXXXXXX. Is there any value in changing the query to:
SELECT * FROM mytable WHERE
((class='A' AND num IN (8198747, 1176312, ...)) OR
(class='B' AND num IN (1247910, 1248192, ...)) OR
(class='F' AND num IN (7244626, 9084903, ...)) OR
--...for each class in the query
)
after adding a new index cn_idx on class and num, in that order?
I think it won't be much faster, since class is just one char, and thus the number of BTREE lookups will be the same. But, each subtree will be shorter. Thoughts?
In short
just stick to OR
the index on num is the only index that will help this query
an composite index on (num,class) has negligible effect, since num is already very selective
Two other ways to write it, using UNION ALL
SELECT * FROM mytable
WHERE (num=8198747 AND class='A')
UNION ALL
SELECT * FROM mytable
WHERE (num=1646463 AND class='B')
UNION ALL
SELECT * FROM mytable
WHERE (num=4099442 AND class='C')
UNION ALL
... etc ...
This may work well if you don't have too many num/class pairs, as each one will individually perform an index seek. (A composite index on num/class will work better than num and class indexes single-field indexes. class/num is less selective)
The second way uses JOIN mechanics, by making a virtual table out of the num/class pairs:
SELECT t.*
FROM mytable t
JOIN (
select 8198747 as num, 'A' as class union all
select 1646463, 'B' union all
select 4099442, 'C' union all
... etc ...
) v on v.num=t.num and v.class=t.class
Performance comparison
Create a table
create table mytable (
id int auto_increment primary key,
num int,
class char(1),
other varchar(10),
date timestamp default current_timestamp) ENGINE InnoDB;
Fill it up with 1 million records
(Note: data properties - selectivity: num ~ 1, class ~ 1/26)
insert into mytable(num, class, other)
select rand()*100000000, char(rand()*26+65), concat('',rand()*10000000)
from
(select 1 a 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 union all select 0) a,
(select 1 a 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 union all select 0) b,
(select 1 a 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 union all select 0) c,
(select 1 a 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 union all select 0) d,
(select 1 a 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 union all select 0) e,
(select 1 a 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 union all select 0) f
Create the indexes
create index nc_num on mytable(num);
create index nc_class on mytable(class);
Select using OR
select * from mytable
WHERE
(num=38142659 and class='T') OR
(num=42476845 and class='E') OR
(num=45205882 and class='B') OR
(num=84861596 and class='K') OR
..... 100 in total
Output of Show profiles: (run set profiling=1; once. then run the queries. run show profiles to see the last timings)
Duration: 0.00003025
Explain extended (add explain extended before the query)
"id";"select_type";"table";"type";"possible_keys";"key";"key_len";"ref";"rows";"Extra"
"1";"SIMPLE";"mytable";"range";"nc_num,nc_class";"nc_num";"5";NULL;"125";"Using where"
Select using UNION ALL between num/class
SELECT * FROM mytable WHERE (num=38142659 AND class='T') UNION ALL
SELECT * FROM mytable WHERE (num=42476845 AND class='E') UNION ALL
SELECT * FROM mytable WHERE (num=45205882 AND class='B') UNION ALL
SELECT * FROM mytable WHERE (num=84861596 AND class='K') UNION ALL
.... 100 in total
Show Profile
Duration: 0.00069525
Explain extended
"id";"select_type";"table";"type";"possible_keys";"key";"key_len";"ref";"rows";"Extra"
"1";"PRIMARY";"mytable";"ref";"nc_num,nc_class";"nc_num";"5";"const";"1";"Using where"
"2";"UNION";"mytable";"ref";"nc_num,nc_class";"nc_num";"5";"const";"1";"Using where"
"3";"UNION";"mytable";"ref";"nc_num,nc_class";"nc_num";"5";"const";"1";"Using where"
"4";"UNION";"mytable";"ref";"nc_num,nc_class";"nc_num";"5";"const";"1";"Using where"
... etc
Select using Union All to build up a virtual table
SELECT t.*
FROM mytable t
JOIN (
select 41805446 num, 'X' collate utf8_general_ci class union all
select 84867135, 'P' union all
select 52747446, 'R' union all
.... etc...
) v on v.num=t.num and v.class=t.class
Show profile
Duration: 0.00026100
Explain extended
"id";"select_type";"table";"type";"possible_keys";"key";"key_len";"ref";"rows";"Extra"
"1";"PRIMARY";"<derived2>";"ALL";NULL;NULL;NULL;NULL;"100";""
"1";"PRIMARY";"t";"ref";"nc_num";"nc_num";"5";"v.num";"1";"Using where"
"2";"DERIVED";NULL;NULL;NULL;NULL;NULL;NULL;NULL;"No tables used"
"3";"UNION";NULL;NULL;NULL;NULL;NULL;NULL;NULL;"No tables used"
"4";"UNION";NULL;NULL;NULL;NULL;NULL;NULL;NULL;"No tables used"
....
"101";"UNION";NULL;NULL;NULL;NULL;NULL;NULL;NULL;"No tables used"
NULL;"UNION RESULT";"<union2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,...>";"ALL";NULL;NULL;NULL;NULL;NULL;""
Select using IN
SELECT * FROM mytable WHERE
(class='A' and num in (28538065
)) or (class='B' and num in (70851926
,90457823
,94804149
)) or (class='C' and num in (74179050
,43280101
,24562525
,56859448
,38226813
,33532373
,93501613
,28634136
,8204338
,15636810
)) or (class='D' and num in (26672499
.... etc
Show profile
Duration: 0.00003125
Explain extended
"id";"select_type";"table";"type";"possible_keys";"key";"key_len";"ref";"rows";"Extra"
"1";"SIMPLE";"mytable";"range";"nc_num,nc_class";"nc_num";"5";NULL;"136";"Using where"