select range from dual in mariadb - mariadb

I am using MariaDB and I would like to generate a dummy result set of a number range. The following works well:
select 0.0 as x
union select 0.1
union select 0.2
union select 0.3
union select 0.4
union select 0.5
union select 0.6
union select 0.7
union select 0.8
union select 0.9
union select 1.0
from dual
But is there a shorter form?

For MariaDB 10.1+ you can use a Sequence table:
SELECT 0.1 * seq AS col
FROM seq_0_to_10
See the demo.

Using VALUES:
VALUES (0.0),(0.1),(0.2),(0.3),(0.4),(0.5),(0.6),(0.7),(0.8),(0.9),(1.0)
It makes sense when the list is static.
db<>fiddle demo
MySQL version will require adding ROW
VALUES ROW(0.0), ROW(0.1), ...

You could use a recursive CTE here:
WITH RECURSIVE cte (n) AS (
SELECT 0.0
UNION ALL
SELECT n + 0.1 FROM cte WHERE n < 1.0
)
SELECT * FROM cte;
Demo

Related

plsql count by date and sum up to the date

I'd like to have a plsql request that count the number of row by date and the sum of row up to the date.
The source will be somethings like this (hundreds of dates):
2019.05.01
2019.05.01
2019.05.02
2019.05.03
2019.05.03
2019.05.03
...
and the result:
date nb sum
-------------------
2019.05.01 2 2
2019.05.02 1 3
2019.05.03 3 6
. . .
The key here is to use an Aggregate Function as an Analytical function which is what the SUM(COUNT(dt)) OVER (ORDER BY dt) in the query below is doing.
WITH dates AS
(
SELECT to_date('2019.05.01', 'YYYY.MM.DD') AS dt FROM dual UNION ALL
SELECT to_date('2019.05.01', 'YYYY.MM.DD') AS dt FROM dual UNION ALL
SELECT to_date('2019.05.02', 'YYYY.MM.DD') AS dt FROM dual UNION ALL
SELECT to_date('2019.05.03', 'YYYY.MM.DD') AS dt FROM dual UNION ALL
SELECT to_date('2019.05.03', 'YYYY.MM.DD') AS dt FROM dual UNION ALL
SELECT to_date('2019.05.03', 'YYYY.MM.DD') AS dt FROM dual
)
SELECT dt, COUNT(dt) AS nb, SUM(COUNT(dt)) OVER (ORDER BY dt) AS sum
FROM dates
GROUP BY dt
;
First half is relatively easy. Something like
SELECT date, count(*) from table GROUP BY date ORDER BY date;
But I'm not sure about the cumulative sum. If it's a manual process then I'd probably just import into Excel and do it there to be honest.

SQL syntax error or missing database (near "(": syntax error) when using union

I am trying to use union but i get this vague syntax error. I Can get each query to run seperately, but when i try to use union i get this error.
(SELECT s.sname, COUNT(s.sname) AS number
FROM sailor s, boat b
WHERE b.rating <= s.rating
GROUP BY s.sname)
UNION
(SELECT s.sname, 0 AS number
FROM sailor s
WHERE NOT EXISTS(
SELECT * FROM boat b
WHERE s.rating >= b.rating));
In SQL, only subqueries use parentheses. In a compound query, the individual SELECTs must be written without them:
SELECT s.sname, COUNT(s.sname) AS number
FROM sailor s, boat b
WHERE b.rating <= s.rating
GROUP BY s.sname
UNION
SELECT s.sname, 0 AS number
FROM sailor s
WHERE NOT EXISTS(
SELECT * FROM boat b
WHERE s.rating >= b.rating);
And in this specific case, you might just want to use an outer join:
SELECT s.sname,
IFNULL(COUNT(b.rating), 0) AS number
FROM sailor AS s
LEFT JOIN boat AS b
ON b.rating <= s.rating;

How to SELECT values not found in a table?

I would like to determine particular IDs that are not present in a table.
For example, I have the IDs 1, 2 and 3 and want to know if they exist in the table.
Essentially this would boil down to:
SELECT id FROM (
SELECT 1 AS id
UNION
SELECT 2 AS id
UNION
SELECT 3 AS id
)
WHERE
NOT EXISTS (SELECT * FROM table WHERE table.id = id)
Suppose table had the IDs 1 and 4, then this would yield 2 and 3.
Are there more elegant / concise / faster ways to get those IDs in SQLite ?
The compound SELECT operator EXCEPT allows you to do something similar to NOT EXISTS:
SELECT 1 AS id UNION ALL
SELECT 2 UNION ALL
SELECT 3
EXCEPT
SELECT id FROM MyTable
Beginning with SQLite 3.8.3, you can use VALUES everywhere you could use SELECT, but this is just a different syntax:
VALUES (1),
(2),
(3)
EXCEPT
SELECT id FROM MyTable

multi table insert fecthing value from another table

I have tables - FAKE_CUST, PRE_CUST, NORMAL_CUST. Based on the constraint present in FAKE_CUST table, the value has to be brought to either PRE_CUST or NORMAL_CUST.
I am using the follwing code:
INSERT ALL
INTO PRE_CUST(CUST_ID, TOTAL_COST_TRANS) (SELECT DISTINCT CUST_ID,C FROM (
SELECT CUST_ID, SUM(COST_TRANS) OVER (PARTITION BY CUST_ID) as C FROM FAKE_CUST) WHERE C>1000)
INTO NORMAL_CUST(CUST_ID, TOTAL_COST_TRANS) (SELECT DISTINCT CUST_ID,C FROM (
SELECT CUST_ID, SUM(COST_TRANS) OVER (PARTITION BY CUST_ID) as C FROM FAKE_CUST) WHERE C<1000)
SELECT 1 FROM DUAL;
The syntax which you have used for multi-table insert is not correct to start with.
The WHEN clause, which evaluates the condition for insert, has to come before insert_intoclause.
Your query should look like this:
INSERT ALL
WHEN c > 1000 THEN
INTO pre_cust (cust_id, total_cost_trans)
WHEN c < 1000 THEN
INTO normal_cust (cust_id, total_cost_trans)
SELECT CUST_ID, SUM(COST_TRANS) OVER (PARTITION BY CUST_ID) as C
FROM FAKE_CUST

Select numbers between a range (1 to 100) in sqlite

I know some of the solutions in SQL but couldn't find any of them from SQlite.
I just want to execute a select query that returns a resultset of numbers ranging from 1 to 100.
Numbers
1
2
3
4
......
5
A correction: I don't actually have a table at all. (however a solution is encouraged with a virtual table like dual in MySQL)
Thanks sgmentzer!
Inspired by your answer I went ahead and also found this:
WITH RECURSIVE
cnt(x) AS (
SELECT 1
UNION ALL
SELECT x+1 FROM cnt
LIMIT 100000
)
SELECT x FROM cnt;
How about
SELECT * FROM myTable WHERE myNumber >= 1 AND myNumber <= 100;
?
Example subquery to generate the series 1 <= n <= 100000 in SQLite. No table is created or used.
select 1+e+d*10+c*100+b*1000+a*10000 as n from
(select 0 as a 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),
(select 0 as b 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),
(select 0 as c 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),
(select 0 as d 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),
(select 0 as e 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);
I don't think SQLite has a clean way to do this, so you'll need to use a virtual table interface. SQLite ships one for 'C', and apsw has one for python as I'll demonstrate below. Here's documentation for the APSW Virtual Table interface.
#!/usr/bin/python
import apsw,tempfile
### Opening/creating database
filename=tempfile.mktemp() #insecure - do not use in production code
connection=apsw.Connection(filename)
cursor=connection.cursor()
# This gets registered with the Connection
class Source:
def Create(self, db, modulename, dbname, tablename, *args):
schema="create table foo( dummy integer )"
return schema,Table()
Connect=Create
# Represents a table
class Table:
def __init__(self):
pass
def BestIndex(self, constraints, orderbys):
used = []
self.constraints = []
ucount = 0
for c in constraints:
if c[1] in (
apsw.SQLITE_INDEX_CONSTRAINT_GT,
apsw.SQLITE_INDEX_CONSTRAINT_GE,
apsw.SQLITE_INDEX_CONSTRAINT_LT,
apsw.SQLITE_INDEX_CONSTRAINT_LE,
apsw.SQLITE_INDEX_CONSTRAINT_EQ,
):
used.append( ucount ) #tell sqlite we want to use this one
self.constraints.append( c[1] ) #save some for later
else:
used.append( None ) #skip anything we don't understand
ucount += 1
return ( used, # used constraints list
0, # index number - no biggie we only support one right now
)
def Open(self):
return Cursor(self)
def Disconnect(self):
pass
Destroy=Disconnect
# Represents a cursor
class Cursor:
def __init__(self, table):
self.table=table
def Filter(self, indexnum, indexname, constraintargs):
start = 0
self.end = 4000000000
#map constraint arguments to start and end of generation
for tc, ca in zip( self.table.constraints, constraintargs ):
if tc == apsw.SQLITE_INDEX_CONSTRAINT_EQ:
start = ca
self.end = ca
elif tc == apsw.SQLITE_INDEX_CONSTRAINT_LE:
if self.end > ca:
self.end = ca
elif tc == apsw.SQLITE_INDEX_CONSTRAINT_LT:
if self.end >= ca:
self.end = ca
elif tc == apsw.SQLITE_INDEX_CONSTRAINT_GE:
if start < ca:
start = ca
elif tc == apsw.SQLITE_INDEX_CONSTRAINT_GT:
if start >= ca:
start = ca
self.pos = start
def Eof(self):
return self.pos > self.end
def Rowid(self):
return self.pos
def Next(self):
self.pos+=1
def Close(self):
pass
# Register the module as intsource, you can make a bunch if needed
connection.createmodule("intsource", Source())
# Create virtual table to use intsource
cursor.execute("create virtual table uints using intsource()")
# Do some counting
for i in cursor.execute("SELECT rowid FROM uints WHERE rowid BETWEEN 1 AND 100"):
print i
This implements a virtual-table type named "intsource", which by default counts from 0 to 4*10^9. It supports directly filtering by equality and comparison, but any other constraints will still be filtered out by sqlite. Virtual tables are a very powerful concept you can do a lot with, this is probably one of the simplest uses for them. Also, thank you for a good excuse to try out a new virtual table API.
SELECT * FROM Numbers limit 1, 100;
If your goal is to select actual records from a table with values between 1 and 100, use BETWEEN as shown by the other respondents.
If your goal is to generate a sequence of numbers from 1 to 100 without having a table to base it on, I don't believe SQLite has a feature that does this.
SELECT * FROM myTable WHERE myNumber BETWEEN 1 AND 100;
This is more efficient than using 2 WHERE clauses.

Resources