27
loading...
This website collects cookies to deliver better user experience
sqlite3
and see which URL you visited most often:$ sqlite3 ~/'Library/Application Support/Google/Chrome/Default/History'
SQLite version 3.32.3 2020-06-18 14:16:19
Enter ".help" for usage hints.
sqlite> .headers on
sqlite> select url, title from urls order by visit_count desc limit 1;
url|title
https://twitter.com/|Home / Twitter
#!
, so we need to write a small header to trick it into our special mode. Here's Hello, World!:#!/bin/bash
tail -n +5 "$0" | sqlite3
exit $?
select "Hello, World!";
$ ./hello.sql
Hello, World!
"$0"
in shell means means current file name - and we need to put it in ""
in case path contains spaces, as that breaks shell scripts. tail -n +5
means print everything from a file from line 5 onwards. | sqlite3
means start SQLite and pipe that stuff into its input.sqlite3 <file.sql
:$ cat hello2.sql
select "Hello, World!";
$ sqlite3 <hello2.sql
Hello, World!
echo
it from within shell - this is not really recommended for anything nontrivial, as we need to deal with shell quoting and evaluation issues:$ echo 'select "Hello, World!";' | sqlite3
Hello, World!
$ sqlite3 <<<'select "Hello, World!";'
Hello, World!
tail
header in the examples, just the SQL part.select * from generate_series(1, 10);
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 union
select 10;
with recursive generate_series(value) as (
select 1
union all select value+1
from generate_series
where value + 1 <= 10
)
select value from generate_series;
#!/bin/bash
tail -n +5 "$0" | sqlite3
exit $?
with recursive generate_series(value) as (
select 1
union all select value+1
from generate_series
where value + 1 <= 100
)
select
case
when value % 15 = 0 then 'FizzBuzz'
when value % 5 = 0 then 'Buzz'
when value % 3 = 0 then 'Fizz'
else value
end
from generate_series;
a
), and ignore all the rest (b
, i
):#!/bin/bash
tail -n +5 "$0" | sqlite3
exit $?
with recursive fib(a, b, i) as (
select 1, 1, 1
union all
select b, a + b, i + 1
from fib
where i + 1 <= 100
)
select a from fib;
$ ./fib.sql
1
1
2
3
5
8
13
21
34
55
..
5.16807088548583e+19
8.36211434898484e+19
1.35301852344707e+20
2.18922995834555e+20
3.54224848179262e+20
create table csv(data);
insert into csv values('first name,last name,favorite language
Alice,Smith,Ruby
Bob,Smith,Python
Charlie,Brown,JavaScript
Daniel,Clark,PHP
Ed,Jones,C
Frank,Smith,HTML
Gary,Johnson,CSS
Heather,Williams,JavaScript
Ivan,Smith,Ruby
Jack,Jones,JavaScript
John,Brown,PHP
Karen,Clark,JavaScript
Larry,Jones,HTML
Mike,Williams,CSS
Nathan,Smith,Ruby
Oscar,Brown,JavaScript
Peter,Clark,PHP
Quinn,Jones,JavaScript
Ralph,Smith,HTML
Sally,Williams,CSS
Tom,Smith,Ruby
Will,Jones,JavaScript
Xavier,Brown,PHP
Yvonne,Clark,JavaScript
Zachary,Jones,HTML
');
create table lines(lineno, line);
insert into lines
with recursive split(lineno, line, str) as (
select 0, null, data from csv
union all
select
lineno + 1,
substr(str, 0, instr(str, char(10))),
substr(str, instr(str, char(10))+1)
from split where str != ''
) select lineno, line from split where line is not null;
"A\nB\nC\n"
into "A"
and "B\nC\n"
- until result is empty. Then it throws out those strings.\n
, so we need to do char(10)
. It's also important that this input ends with \n
, otherwise the expression will loop forever. We could add some more checks to deal with it, but let's just deal with the happy path..headers on
, SQL output is separated by |
by default):lineno|line
1|first name,last name,favorite language
2|Alice,Smith,Ruby
3|Bob,Smith,Python
4|Charlie,Brown,JavaScript
5|Daniel,Clark,PHP
...
,
we need to (line||',')
for our loop to work (||
is string concatenation, not logical or):create table cells(lineno, colno, cell);
insert into cells
with recursive split(lineno, colno, cell, str) as (
select lineno, 0, null, (line||',') from lines
union all
select
lineno,
colno + 1,
substr(str, 0, instr(str, ',')),
substr(str, instr(str, ',')+1)
from split where str != ''
) select lineno, colno, cell from split where cell is not null;
lineno|colno|cell
1|1|first name
1|2|last name
1|3|favorite language
2|1|Alice
2|2|Smith
2|3|Ruby
3|1|Bob
3|2|Smith
...
create table cellvals(lineno, k, v);
insert into cellvals
select c.lineno, h.cell, c.cell from cells h
inner join cells c
on c.colno = h.colno and h.lineno = 1 and c.lineno != 1;
lineno|k|v
2|first name|Alice
2|last name|Smith
2|favorite language|Ruby
3|first name|Bob
3|last name|Smith
3|favorite language|Python
...
create table preferences(full_name, language);
insert into preferences
select fn.v||' '||ln.v, fl.v
from cellvals fn
inner join cellvals ln
on fn.k='first name' and ln.k='last name' and fn.lineno = ln.lineno
inner join cellvals fl
on fl.k='favorite language' and fn.lineno = fl.lineno;
full_name|language
Alice Smith|Ruby
Bob Smith|Python
Charlie Brown|JavaScript
...
select language || ',' || group_concat(full_name, ',') from preferences group by language;
$ ./csv.sql
C,Ed Jones
CSS,Gary Johnson,Mike Williams,Sally Williams
HTML,Frank Smith,Larry Jones,Ralph Smith,Zachary Jones
JavaScript,Charlie Brown,Heather Williams,Jack Jones,Karen Clark,Oscar Brown,Quinn Jones,Will Jones,Yvonne Clark
PHP,Daniel Clark,John Brown,Peter Clark,Xavier Brown
Python,Bob Smith
Ruby,Alice Smith,Ivan Smith,Nathan Smith,Tom Smith
with
csv(data) as (
select 'first name,last name,favorite language
Alice,Smith,Ruby
Bob,Smith,Python
Charlie,Brown,JavaScript
Daniel,Clark,PHP
Ed,Jones,C
Frank,Smith,HTML
Gary,Johnson,CSS
Heather,Williams,JavaScript
Ivan,Smith,Ruby
Jack,Jones,JavaScript
John,Brown,PHP
Karen,Clark,JavaScript
Larry,Jones,HTML
Mike,Williams,CSS
Nathan,Smith,Ruby
Oscar,Brown,JavaScript
Peter,Clark,PHP
Quinn,Jones,JavaScript
Ralph,Smith,HTML
Sally,Williams,CSS
Tom,Smith,Ruby
Will,Jones,JavaScript
Xavier,Brown,PHP
Yvonne,Clark,JavaScript
Zachary,Jones,HTML
'
),
lines(lineno, line) as (
with recursive split(lineno, line, str) as (
select 0, null, data from csv
union all
select
lineno + 1,
substr(str, 0, instr(str, char(10))),
substr(str, instr(str, char(10))+1)
from split where str != ''
) select lineno, line from split where line is not null
),
cells(lineno, colno, cell) as (
with recursive split(lineno, colno, cell, str) as (
select lineno, 0, null, (line||',') from lines
union all
select
lineno,
colno + 1,
substr(str, 0, instr(str, ',')),
substr(str, instr(str, ',')+1)
from split where str != ''
) select lineno, colno, cell from split where cell is not null
),
cellvals(lineno, k, v) as (
select c.lineno, h.cell, c.cell from cells h
inner join cells c
on c.colno = h.colno and h.lineno = 1 and c.lineno != 1
),
preferences(full_name, language) as (
select fn.v||' '||ln.v, fl.v
from cellvals fn
inner join cellvals ln
on fn.k='first name' and ln.k='last name' and fn.lineno = ln.lineno
inner join cellvals fl
on fl.k='favorite language' and fn.lineno = fl.lineno
)
select language || ',' || group_concat(full_name, ',') from preferences group by language;