mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-20 18:10:07 +00:00
split up 10-min page
This commit is contained in:
parent
8c287e25fb
commit
00ea4caeec
8 changed files with 807 additions and 2 deletions
|
|
@ -64,4 +64,4 @@ awk-like features: mlr filter and mlr put
|
|||
See also
|
||||
----------------------------------------------------------------
|
||||
|
||||
See :doc:`reference` for more on Miller's subcommands ``cat``, ``cut``, ``head``, ``sort``, ``tac``, ``tail``, ``top``, and ``uniq``, as well as awk-like ``mlr filter`` and ``mlr put``.
|
||||
See :doc:`reference-verbs` for more on Miller's subcommands ``cat``, ``cut``, ``head``, ``sort``, ``tac``, ``tail``, ``top``, and ``uniq``, as well as :doc:`reference-dsl` for more on the awk-like ``mlr filter`` and ``mlr put``.
|
||||
|
|
|
|||
|
|
@ -48,4 +48,4 @@ awk-like features: mlr filter and mlr put
|
|||
See also
|
||||
----------------------------------------------------------------
|
||||
|
||||
See :doc:`reference` for more on Miller's subcommands ``cat``, ``cut``, ``head``, ``sort``, ``tac``, ``tail``, ``top``, and ``uniq``, as well as awk-like ``mlr filter`` and ``mlr put``.
|
||||
See :doc:`reference-verbs` for more on Miller's subcommands ``cat``, ``cut``, ``head``, ``sort``, ``tac``, ``tail``, ``top``, and ``uniq``, as well as :doc:`reference-dsl` for more on the awk-like ``mlr filter`` and ``mlr put``.
|
||||
|
|
|
|||
185
docs/log-processing-examples.rst
Normal file
185
docs/log-processing-examples.rst
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
..
|
||||
PLEASE DO NOT EDIT DIRECTLY. EDIT THE .rst.in FILE PLEASE.
|
||||
|
||||
Log-processing examples
|
||||
----------------------------------------------------------------
|
||||
|
||||
Another of my favorite use-cases for Miller is doing ad-hoc processing of log-file data. Here's where DKVP format really shines: one, since the field names and field values are present on every line, every line stands on its own. That means you can ``grep`` or what have you. Also it means not every line needs to have the same list of field names ("schema").
|
||||
|
||||
Again, all the examples in the CSV section apply here -- just change the input-format flags. But there's more you can do when not all the records have the same shape.
|
||||
|
||||
Writing a program -- in any language whatsoever -- you can have it print out log lines as it goes along, with items for various events jumbled together. After the program has finished running you can sort it all out, filter it, analyze it, and learn from it.
|
||||
|
||||
Suppose your program has printed something like this::
|
||||
|
||||
$ cat log.txt
|
||||
op=enter,time=1472819681
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
time=1472819690,batch_size=100,num_filtered=237
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A1,hit=1
|
||||
time=1472819705,batch_size=100,num_filtered=348
|
||||
op=cache,type=A4,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
time=1472819713,batch_size=100,num_filtered=493
|
||||
op=cache,type=A9,hit=1
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=1
|
||||
time=1472819720,batch_size=100,num_filtered=554
|
||||
op=cache,type=A1,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=0
|
||||
op=cache,type=A4,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
time=1472819736,batch_size=100,num_filtered=612
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A4,hit=1
|
||||
op=cache,type=A1,hit=1
|
||||
op=cache,type=A9,hit=0
|
||||
op=cache,type=A9,hit=0
|
||||
time=1472819742,batch_size=100,num_filtered=728
|
||||
|
||||
Each print statement simply contains local information: the current timestamp, whether a particular cache was hit or not, etc. Then using either the system ``grep`` command, or Miller's ``having-fields``, or ``is_present``, we can pick out the parts we want and analyze them::
|
||||
|
||||
$ grep op=cache log.txt \
|
||||
| mlr --idkvp --opprint stats1 -a mean -f hit -g type then sort -f type
|
||||
type hit_mean
|
||||
A1 0.857143
|
||||
A4 0.714286
|
||||
A9 0.090909
|
||||
|
||||
::
|
||||
|
||||
$ mlr --from log.txt --opprint \
|
||||
filter 'is_present($batch_size)' \
|
||||
then step -a delta -f time,num_filtered \
|
||||
then sec2gmt time
|
||||
time batch_size num_filtered time_delta num_filtered_delta
|
||||
2016-09-02T12:34:50Z 100 237 0 0
|
||||
2016-09-02T12:35:05Z 100 348 15 111
|
||||
2016-09-02T12:35:13Z 100 493 8 145
|
||||
2016-09-02T12:35:20Z 100 554 7 61
|
||||
2016-09-02T12:35:36Z 100 612 16 58
|
||||
2016-09-02T12:35:42Z 100 728 6 116
|
||||
|
||||
Alternatively, we can simply group the similar data for a better look::
|
||||
|
||||
$ mlr --opprint group-like log.txt
|
||||
op time
|
||||
enter 1472819681
|
||||
|
||||
op type hit
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A4 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A9 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 1
|
||||
cache A1 0
|
||||
cache A4 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 0
|
||||
cache A4 0
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
|
||||
time batch_size num_filtered
|
||||
1472819690 100 237
|
||||
1472819705 100 348
|
||||
1472819713 100 493
|
||||
1472819720 100 554
|
||||
1472819736 100 612
|
||||
1472819742 100 728
|
||||
|
||||
::
|
||||
|
||||
$ mlr --opprint group-like then sec2gmt time log.txt
|
||||
op time
|
||||
enter 2016-09-02T12:34:41Z
|
||||
|
||||
op type hit
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A4 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A9 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 1
|
||||
cache A1 0
|
||||
cache A4 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 0
|
||||
cache A4 0
|
||||
cache A9 0
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
cache A4 1
|
||||
cache A1 1
|
||||
cache A9 0
|
||||
cache A9 0
|
||||
|
||||
time batch_size num_filtered
|
||||
2016-09-02T12:34:50Z 100 237
|
||||
2016-09-02T12:35:05Z 100 348
|
||||
2016-09-02T12:35:13Z 100 493
|
||||
2016-09-02T12:35:20Z 100 554
|
||||
2016-09-02T12:35:36Z 100 612
|
||||
2016-09-02T12:35:42Z 100 728
|
||||
28
docs/log-processing-examples.rst.in
Normal file
28
docs/log-processing-examples.rst.in
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
Log-processing examples
|
||||
----------------------------------------------------------------
|
||||
|
||||
Another of my favorite use-cases for Miller is doing ad-hoc processing of log-file data. Here's where DKVP format really shines: one, since the field names and field values are present on every line, every line stands on its own. That means you can ``grep`` or what have you. Also it means not every line needs to have the same list of field names ("schema").
|
||||
|
||||
Again, all the examples in the CSV section apply here -- just change the input-format flags. But there's more you can do when not all the records have the same shape.
|
||||
|
||||
Writing a program -- in any language whatsoever -- you can have it print out log lines as it goes along, with items for various events jumbled together. After the program has finished running you can sort it all out, filter it, analyze it, and learn from it.
|
||||
|
||||
Suppose your program has printed something like this::
|
||||
|
||||
POKI_RUN_COMMAND{{cat log.txt}}HERE
|
||||
|
||||
Each print statement simply contains local information: the current timestamp, whether a particular cache was hit or not, etc. Then using either the system ``grep`` command, or Miller's ``having-fields``, or ``is_present``, we can pick out the parts we want and analyze them::
|
||||
|
||||
POKI_INCLUDE_AND_RUN_ESCAPED(10-1.sh)HERE
|
||||
|
||||
::
|
||||
|
||||
POKI_INCLUDE_AND_RUN_ESCAPED(10-2.sh)HERE
|
||||
|
||||
Alternatively, we can simply group the similar data for a better look::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --opprint group-like log.txt}}HERE
|
||||
|
||||
::
|
||||
|
||||
POKI_RUN_COMMAND{{mlr --opprint group-like then sec2gmt time log.txt}}HERE
|
||||
72
docs/quick-examples.rst
Normal file
72
docs/quick-examples.rst
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
..
|
||||
PLEASE DO NOT EDIT DIRECTLY. EDIT THE .rst.in FILE PLEASE.
|
||||
|
||||
Quick examples
|
||||
================================================================
|
||||
|
||||
Column select::
|
||||
|
||||
% mlr --csv cut -f hostname,uptime mydata.csv
|
||||
|
||||
Add new columns as function of other columns::
|
||||
|
||||
% mlr --nidx put '$sum = $7 < 0.0 ? 3.5 : $7 + 2.1*$8' *.dat
|
||||
|
||||
Row filter::
|
||||
|
||||
% mlr --csv filter '$status != "down" && $upsec >= 10000' *.csv
|
||||
|
||||
Apply column labels and pretty-print::
|
||||
|
||||
% grep -v '^#' /etc/group | mlr --ifs : --nidx --opprint label group,pass,gid,member then sort -f group
|
||||
|
||||
Join multiple data sources on key columns::
|
||||
|
||||
% mlr join -j account_id -f accounts.dat then group-by account_name balances.dat
|
||||
|
||||
Multiple formats including JSON::
|
||||
|
||||
% mlr --json put '$attr = sub($attr, "([0-9]+)_([0-9]+)_.*", "\1:\2")' data/*.json
|
||||
|
||||
Aggregate per-column statistics::
|
||||
|
||||
% mlr stats1 -a min,mean,max,p10,p50,p90 -f flag,u,v data/*
|
||||
|
||||
Linear regression::
|
||||
|
||||
% mlr stats2 -a linreg-pca -f u,v -g shape data/*
|
||||
|
||||
Aggregate custom per-column statistics::
|
||||
|
||||
% mlr put -q '@sum[$a][$b] += $x; end {emit @sum, "a", "b"}' data/*
|
||||
|
||||
Iterate over data using DSL expressions::
|
||||
|
||||
% mlr --from estimates.tbl put '
|
||||
for (k,v in $*) {
|
||||
if (is_numeric(v) && k =~ "^[t-z].*$") {
|
||||
$sum += v; $count += 1
|
||||
}
|
||||
}
|
||||
$mean = $sum / $count # no assignment if count unset
|
||||
'
|
||||
|
||||
Run DSL expressions from a script file::
|
||||
|
||||
% mlr --from infile.dat put -f analyze.mlr
|
||||
|
||||
Split/reduce output to multiple filenames::
|
||||
|
||||
% mlr --from infile.dat put 'tee > "./taps/data-".$a."-".$b, $*'
|
||||
|
||||
Compressed I/O::
|
||||
|
||||
% mlr --from infile.dat put 'tee | "gzip > ./taps/data-".$a."-".$b.".gz", $*'
|
||||
|
||||
Interoperate with other data-processing tools using standard pipes::
|
||||
|
||||
% mlr --from infile.dat put -q '@v=$*; dump | "jq .[]"'
|
||||
|
||||
Tap/trace::
|
||||
|
||||
% mlr --from infile.dat put '(NR % 1000 == 0) { print > stderr, "Checkpoint ".NR}'
|
||||
69
docs/quick-examples.rst.in
Normal file
69
docs/quick-examples.rst.in
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
Quick examples
|
||||
================================================================
|
||||
|
||||
Column select::
|
||||
|
||||
% mlr --csv cut -f hostname,uptime mydata.csv
|
||||
|
||||
Add new columns as function of other columns::
|
||||
|
||||
% mlr --nidx put '$sum = $7 < 0.0 ? 3.5 : $7 + 2.1*$8' *.dat
|
||||
|
||||
Row filter::
|
||||
|
||||
% mlr --csv filter '$status != "down" && $upsec >= 10000' *.csv
|
||||
|
||||
Apply column labels and pretty-print::
|
||||
|
||||
% grep -v '^#' /etc/group | mlr --ifs : --nidx --opprint label group,pass,gid,member then sort -f group
|
||||
|
||||
Join multiple data sources on key columns::
|
||||
|
||||
% mlr join -j account_id -f accounts.dat then group-by account_name balances.dat
|
||||
|
||||
Multiple formats including JSON::
|
||||
|
||||
% mlr --json put '$attr = sub($attr, "([0-9]+)_([0-9]+)_.*", "\1:\2")' data/*.json
|
||||
|
||||
Aggregate per-column statistics::
|
||||
|
||||
% mlr stats1 -a min,mean,max,p10,p50,p90 -f flag,u,v data/*
|
||||
|
||||
Linear regression::
|
||||
|
||||
% mlr stats2 -a linreg-pca -f u,v -g shape data/*
|
||||
|
||||
Aggregate custom per-column statistics::
|
||||
|
||||
% mlr put -q '@sum[$a][$b] += $x; end {emit @sum, "a", "b"}' data/*
|
||||
|
||||
Iterate over data using DSL expressions::
|
||||
|
||||
% mlr --from estimates.tbl put '
|
||||
for (k,v in $*) {
|
||||
if (is_numeric(v) && k =~ "^[t-z].*$") {
|
||||
$sum += v; $count += 1
|
||||
}
|
||||
}
|
||||
$mean = $sum / $count # no assignment if count unset
|
||||
'
|
||||
|
||||
Run DSL expressions from a script file::
|
||||
|
||||
% mlr --from infile.dat put -f analyze.mlr
|
||||
|
||||
Split/reduce output to multiple filenames::
|
||||
|
||||
% mlr --from infile.dat put 'tee > "./taps/data-".$a."-".$b, $*'
|
||||
|
||||
Compressed I/O::
|
||||
|
||||
% mlr --from infile.dat put 'tee | "gzip > ./taps/data-".$a."-".$b.".gz", $*'
|
||||
|
||||
Interoperate with other data-processing tools using standard pipes::
|
||||
|
||||
% mlr --from infile.dat put -q '@v=$*; dump | "jq .[]"'
|
||||
|
||||
Tap/trace::
|
||||
|
||||
% mlr --from infile.dat put '(NR % 1000 == 0) { print > stderr, "Checkpoint ".NR}'
|
||||
227
docs/sql-examples.rst
Normal file
227
docs/sql-examples.rst
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
..
|
||||
PLEASE DO NOT EDIT DIRECTLY. EDIT THE .rst.in FILE PLEASE.
|
||||
|
||||
SQL examples
|
||||
====================
|
||||
|
||||
.. _sql-output-examples:
|
||||
|
||||
SQL-output examples
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
I like to produce SQL-query output with header-column and tab delimiter: this is CSV but with a tab instead of a comma, also known as TSV. Then I post-process with ``mlr --tsv`` or ``mlr --tsvlite``. This means I can do some (or all, or none) of my data processing within SQL queries, and some (or none, or all) of my data processing using Miller -- whichever is most convenient for my needs at the moment.
|
||||
|
||||
For example, using default output formatting in ``mysql`` we get formatting like Miller's ``--opprint --barred``::
|
||||
|
||||
$ mysql --database=mydb -e 'show columns in mytable'
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
| Field | Type | Null | Key | Default | Extra |
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
| id | bigint(20) | NO | MUL | NULL | |
|
||||
| category | varchar(256) | NO | | NULL | |
|
||||
| is_permanent | tinyint(1) | NO | | NULL | |
|
||||
| assigned_to | bigint(20) | YES | | NULL | |
|
||||
| last_update_time | int(11) | YES | | NULL | |
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
|
||||
Using ``mysql``'s ``-B`` we get TSV output::
|
||||
|
||||
$ mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --opprint cat
|
||||
Field Type Null Key Default Extra
|
||||
id bigint(20) NO MUL NULL -
|
||||
category varchar(256) NO - NULL -
|
||||
is_permanent tinyint(1) NO - NULL -
|
||||
assigned_to bigint(20) YES - NULL -
|
||||
last_update_time int(11) YES - NULL -
|
||||
|
||||
Since Miller handles TSV output, we can do as much or as little processing as we want in the SQL query, then send the rest on to Miller. This includes outputting as JSON, doing further selects/joins in Miller, doing stats, etc. etc.::
|
||||
|
||||
$ mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --ojson --jlistwrap --jvstack cat
|
||||
[
|
||||
{
|
||||
"Field": "id",
|
||||
"Type": "bigint(20)",
|
||||
"Null": "NO",
|
||||
"Key": "MUL",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "category",
|
||||
"Type": "varchar(256)",
|
||||
"Null": "NO",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "is_permanent",
|
||||
"Type": "tinyint(1)",
|
||||
"Null": "NO",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "assigned_to",
|
||||
"Type": "bigint(20)",
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "last_update_time",
|
||||
"Type": "int(11)",
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
}
|
||||
]
|
||||
|
||||
$ mysql --database=mydb -B -e 'select * from mytable' > query.tsv
|
||||
|
||||
$ mlr --from query.tsv --t2p stats1 -a count -f id -g category,assigned_to
|
||||
category assigned_to id_count
|
||||
special 10000978 207
|
||||
special 10003924 385
|
||||
special 10009872 168
|
||||
standard 10000978 524
|
||||
standard 10003924 392
|
||||
standard 10009872 108
|
||||
...
|
||||
|
||||
Again, all the examples in the CSV section apply here -- just change the input-format flags.
|
||||
|
||||
.. _sql-input-examples:
|
||||
|
||||
SQL-input examples
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
One use of NIDX (value-only, no keys) format is for loading up SQL tables.
|
||||
|
||||
Create and load SQL table::
|
||||
|
||||
mysql> CREATE TABLE abixy(
|
||||
a VARCHAR(32),
|
||||
b VARCHAR(32),
|
||||
i BIGINT(10),
|
||||
x DOUBLE,
|
||||
y DOUBLE
|
||||
);
|
||||
Query OK, 0 rows affected (0.01 sec)
|
||||
|
||||
bash$ mlr --onidx --fs comma cat data/medium > medium.nidx
|
||||
|
||||
mysql> LOAD DATA LOCAL INFILE 'medium.nidx' REPLACE INTO TABLE abixy FIELDS TERMINATED BY ',' ;
|
||||
Query OK, 10000 rows affected (0.07 sec)
|
||||
Records: 10000 Deleted: 0 Skipped: 0 Warnings: 0
|
||||
|
||||
mysql> SELECT COUNT(*) AS count FROM abixy;
|
||||
+-------+
|
||||
| count |
|
||||
+-------+
|
||||
| 10000 |
|
||||
+-------+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mysql> SELECT * FROM abixy LIMIT 10;
|
||||
+------+------+------+---------------------+---------------------+
|
||||
| a | b | i | x | y |
|
||||
+------+------+------+---------------------+---------------------+
|
||||
| pan | pan | 1 | 0.3467901443380824 | 0.7268028627434533 |
|
||||
| eks | pan | 2 | 0.7586799647899636 | 0.5221511083334797 |
|
||||
| wye | wye | 3 | 0.20460330576630303 | 0.33831852551664776 |
|
||||
| eks | wye | 4 | 0.38139939387114097 | 0.13418874328430463 |
|
||||
| wye | pan | 5 | 0.5732889198020006 | 0.8636244699032729 |
|
||||
| zee | pan | 6 | 0.5271261600918548 | 0.49322128674835697 |
|
||||
| eks | zee | 7 | 0.6117840605678454 | 0.1878849191181694 |
|
||||
| zee | wye | 8 | 0.5985540091064224 | 0.976181385699006 |
|
||||
| hat | wye | 9 | 0.03144187646093577 | 0.7495507603507059 |
|
||||
| pan | wye | 10 | 0.5026260055412137 | 0.9526183602969864 |
|
||||
+------+------+------+---------------------+---------------------+
|
||||
|
||||
Aggregate counts within SQL::
|
||||
|
||||
mysql> SELECT a, b, COUNT(*) AS count FROM abixy GROUP BY a, b ORDER BY COUNT DESC;
|
||||
+------+------+-------+
|
||||
| a | b | count |
|
||||
+------+------+-------+
|
||||
| zee | wye | 455 |
|
||||
| pan | eks | 429 |
|
||||
| pan | pan | 427 |
|
||||
| wye | hat | 426 |
|
||||
| hat | wye | 423 |
|
||||
| pan | hat | 417 |
|
||||
| eks | hat | 417 |
|
||||
| pan | zee | 413 |
|
||||
| eks | eks | 413 |
|
||||
| zee | hat | 409 |
|
||||
| eks | wye | 407 |
|
||||
| zee | zee | 403 |
|
||||
| pan | wye | 395 |
|
||||
| wye | pan | 392 |
|
||||
| zee | eks | 391 |
|
||||
| zee | pan | 389 |
|
||||
| hat | eks | 389 |
|
||||
| wye | eks | 386 |
|
||||
| wye | zee | 385 |
|
||||
| hat | zee | 385 |
|
||||
| hat | hat | 381 |
|
||||
| wye | wye | 377 |
|
||||
| eks | pan | 371 |
|
||||
| hat | pan | 363 |
|
||||
| eks | zee | 357 |
|
||||
+------+------+-------+
|
||||
25 rows in set (0.01 sec)
|
||||
|
||||
Aggregate counts within Miller::
|
||||
|
||||
$ mlr --opprint uniq -c -g a,b then sort -nr count data/medium
|
||||
a b count
|
||||
zee wye 455
|
||||
pan eks 429
|
||||
pan pan 427
|
||||
wye hat 426
|
||||
hat wye 423
|
||||
pan hat 417
|
||||
eks hat 417
|
||||
eks eks 413
|
||||
pan zee 413
|
||||
zee hat 409
|
||||
eks wye 407
|
||||
zee zee 403
|
||||
pan wye 395
|
||||
hat pan 363
|
||||
eks zee 357
|
||||
|
||||
Pipe SQL output to aggregate counts within Miller::
|
||||
|
||||
$ mysql -D miller -B -e 'select * from abixy' | mlr --itsv --opprint uniq -c -g a,b then sort -nr count
|
||||
a b count
|
||||
zee wye 455
|
||||
pan eks 429
|
||||
pan pan 427
|
||||
wye hat 426
|
||||
hat wye 423
|
||||
pan hat 417
|
||||
eks hat 417
|
||||
eks eks 413
|
||||
pan zee 413
|
||||
zee hat 409
|
||||
eks wye 407
|
||||
zee zee 403
|
||||
pan wye 395
|
||||
wye pan 392
|
||||
zee eks 391
|
||||
zee pan 389
|
||||
hat eks 389
|
||||
wye eks 386
|
||||
hat zee 385
|
||||
wye zee 385
|
||||
hat hat 381
|
||||
wye wye 377
|
||||
eks pan 371
|
||||
hat pan 363
|
||||
eks zee 357
|
||||
224
docs/sql-examples.rst.in
Normal file
224
docs/sql-examples.rst.in
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
SQL examples
|
||||
====================
|
||||
|
||||
.. _sql-output-examples:
|
||||
|
||||
SQL-output examples
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
I like to produce SQL-query output with header-column and tab delimiter: this is CSV but with a tab instead of a comma, also known as TSV. Then I post-process with ``mlr --tsv`` or ``mlr --tsvlite``. This means I can do some (or all, or none) of my data processing within SQL queries, and some (or none, or all) of my data processing using Miller -- whichever is most convenient for my needs at the moment.
|
||||
|
||||
For example, using default output formatting in ``mysql`` we get formatting like Miller's ``--opprint --barred``::
|
||||
|
||||
$ mysql --database=mydb -e 'show columns in mytable'
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
| Field | Type | Null | Key | Default | Extra |
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
| id | bigint(20) | NO | MUL | NULL | |
|
||||
| category | varchar(256) | NO | | NULL | |
|
||||
| is_permanent | tinyint(1) | NO | | NULL | |
|
||||
| assigned_to | bigint(20) | YES | | NULL | |
|
||||
| last_update_time | int(11) | YES | | NULL | |
|
||||
+------------------+--------------+------+-----+---------+-------+
|
||||
|
||||
Using ``mysql``'s ``-B`` we get TSV output::
|
||||
|
||||
$ mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --opprint cat
|
||||
Field Type Null Key Default Extra
|
||||
id bigint(20) NO MUL NULL -
|
||||
category varchar(256) NO - NULL -
|
||||
is_permanent tinyint(1) NO - NULL -
|
||||
assigned_to bigint(20) YES - NULL -
|
||||
last_update_time int(11) YES - NULL -
|
||||
|
||||
Since Miller handles TSV output, we can do as much or as little processing as we want in the SQL query, then send the rest on to Miller. This includes outputting as JSON, doing further selects/joins in Miller, doing stats, etc. etc.::
|
||||
|
||||
$ mysql --database=mydb -B -e 'show columns in mytable' | mlr --itsvlite --ojson --jlistwrap --jvstack cat
|
||||
[
|
||||
{
|
||||
"Field": "id",
|
||||
"Type": "bigint(20)",
|
||||
"Null": "NO",
|
||||
"Key": "MUL",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "category",
|
||||
"Type": "varchar(256)",
|
||||
"Null": "NO",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "is_permanent",
|
||||
"Type": "tinyint(1)",
|
||||
"Null": "NO",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "assigned_to",
|
||||
"Type": "bigint(20)",
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
},
|
||||
{
|
||||
"Field": "last_update_time",
|
||||
"Type": "int(11)",
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": "NULL",
|
||||
"Extra": ""
|
||||
}
|
||||
]
|
||||
|
||||
$ mysql --database=mydb -B -e 'select * from mytable' > query.tsv
|
||||
|
||||
$ mlr --from query.tsv --t2p stats1 -a count -f id -g category,assigned_to
|
||||
category assigned_to id_count
|
||||
special 10000978 207
|
||||
special 10003924 385
|
||||
special 10009872 168
|
||||
standard 10000978 524
|
||||
standard 10003924 392
|
||||
standard 10009872 108
|
||||
...
|
||||
|
||||
Again, all the examples in the CSV section apply here -- just change the input-format flags.
|
||||
|
||||
.. _sql-input-examples:
|
||||
|
||||
SQL-input examples
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
One use of NIDX (value-only, no keys) format is for loading up SQL tables.
|
||||
|
||||
Create and load SQL table::
|
||||
|
||||
mysql> CREATE TABLE abixy(
|
||||
a VARCHAR(32),
|
||||
b VARCHAR(32),
|
||||
i BIGINT(10),
|
||||
x DOUBLE,
|
||||
y DOUBLE
|
||||
);
|
||||
Query OK, 0 rows affected (0.01 sec)
|
||||
|
||||
bash$ mlr --onidx --fs comma cat data/medium > medium.nidx
|
||||
|
||||
mysql> LOAD DATA LOCAL INFILE 'medium.nidx' REPLACE INTO TABLE abixy FIELDS TERMINATED BY ',' ;
|
||||
Query OK, 10000 rows affected (0.07 sec)
|
||||
Records: 10000 Deleted: 0 Skipped: 0 Warnings: 0
|
||||
|
||||
mysql> SELECT COUNT(*) AS count FROM abixy;
|
||||
+-------+
|
||||
| count |
|
||||
+-------+
|
||||
| 10000 |
|
||||
+-------+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mysql> SELECT * FROM abixy LIMIT 10;
|
||||
+------+------+------+---------------------+---------------------+
|
||||
| a | b | i | x | y |
|
||||
+------+------+------+---------------------+---------------------+
|
||||
| pan | pan | 1 | 0.3467901443380824 | 0.7268028627434533 |
|
||||
| eks | pan | 2 | 0.7586799647899636 | 0.5221511083334797 |
|
||||
| wye | wye | 3 | 0.20460330576630303 | 0.33831852551664776 |
|
||||
| eks | wye | 4 | 0.38139939387114097 | 0.13418874328430463 |
|
||||
| wye | pan | 5 | 0.5732889198020006 | 0.8636244699032729 |
|
||||
| zee | pan | 6 | 0.5271261600918548 | 0.49322128674835697 |
|
||||
| eks | zee | 7 | 0.6117840605678454 | 0.1878849191181694 |
|
||||
| zee | wye | 8 | 0.5985540091064224 | 0.976181385699006 |
|
||||
| hat | wye | 9 | 0.03144187646093577 | 0.7495507603507059 |
|
||||
| pan | wye | 10 | 0.5026260055412137 | 0.9526183602969864 |
|
||||
+------+------+------+---------------------+---------------------+
|
||||
|
||||
Aggregate counts within SQL::
|
||||
|
||||
mysql> SELECT a, b, COUNT(*) AS count FROM abixy GROUP BY a, b ORDER BY COUNT DESC;
|
||||
+------+------+-------+
|
||||
| a | b | count |
|
||||
+------+------+-------+
|
||||
| zee | wye | 455 |
|
||||
| pan | eks | 429 |
|
||||
| pan | pan | 427 |
|
||||
| wye | hat | 426 |
|
||||
| hat | wye | 423 |
|
||||
| pan | hat | 417 |
|
||||
| eks | hat | 417 |
|
||||
| pan | zee | 413 |
|
||||
| eks | eks | 413 |
|
||||
| zee | hat | 409 |
|
||||
| eks | wye | 407 |
|
||||
| zee | zee | 403 |
|
||||
| pan | wye | 395 |
|
||||
| wye | pan | 392 |
|
||||
| zee | eks | 391 |
|
||||
| zee | pan | 389 |
|
||||
| hat | eks | 389 |
|
||||
| wye | eks | 386 |
|
||||
| wye | zee | 385 |
|
||||
| hat | zee | 385 |
|
||||
| hat | hat | 381 |
|
||||
| wye | wye | 377 |
|
||||
| eks | pan | 371 |
|
||||
| hat | pan | 363 |
|
||||
| eks | zee | 357 |
|
||||
+------+------+-------+
|
||||
25 rows in set (0.01 sec)
|
||||
|
||||
Aggregate counts within Miller::
|
||||
|
||||
$ mlr --opprint uniq -c -g a,b then sort -nr count data/medium
|
||||
a b count
|
||||
zee wye 455
|
||||
pan eks 429
|
||||
pan pan 427
|
||||
wye hat 426
|
||||
hat wye 423
|
||||
pan hat 417
|
||||
eks hat 417
|
||||
eks eks 413
|
||||
pan zee 413
|
||||
zee hat 409
|
||||
eks wye 407
|
||||
zee zee 403
|
||||
pan wye 395
|
||||
hat pan 363
|
||||
eks zee 357
|
||||
|
||||
Pipe SQL output to aggregate counts within Miller::
|
||||
|
||||
$ mysql -D miller -B -e 'select * from abixy' | mlr --itsv --opprint uniq -c -g a,b then sort -nr count
|
||||
a b count
|
||||
zee wye 455
|
||||
pan eks 429
|
||||
pan pan 427
|
||||
wye hat 426
|
||||
hat wye 423
|
||||
pan hat 417
|
||||
eks hat 417
|
||||
eks eks 413
|
||||
pan zee 413
|
||||
zee hat 409
|
||||
eks wye 407
|
||||
zee zee 403
|
||||
pan wye 395
|
||||
wye pan 392
|
||||
zee eks 391
|
||||
zee pan 389
|
||||
hat eks 389
|
||||
wye eks 386
|
||||
hat zee 385
|
||||
wye zee 385
|
||||
hat hat 381
|
||||
wye wye 377
|
||||
eks pan 371
|
||||
hat pan 363
|
||||
eks zee 357
|
||||
Loading…
Add table
Add a link
Reference in a new issue