TextQL: Execute SQL Against CSV or TSV
github.com
github.com
Also, while I like/applaud Miller (also referenced), xsv has a simpler UI that only handles CSV.
My main hesitation: Its another DSL to learn, there is a big benefit to keeping this kind of work within the SQL world for me (or R, python, etc depending on the user).
On the other hand, getting table stats and frequencies right from the shell is a huge time saver over SQL.
q is out there for years, with a very large community.
q is a command line tool that allows direct execution of SQL-like queries on CSVs/TSVs (and any other tabular text files).
Since q will read stdin and write CVS to stdout you can chain several queries on the command line, or use it in series with other with other commands such as cat, grep, sed, etc.
Highly recommended if you like SQL and deal with delimited files.
Are there any differences with using this instead of CSVKit?
https://csvkit.readthedocs.io/en/1.0.3/
It includes a tool called csvsql.
Example usage -
csvsql --query "select name from data where age > 30" data.csv > new.csvhttps://pandas.pydata.org/pandas-docs/stable/comparison_with...
Csvkit is great with pipes and you can also easily convert between csv tsv and even stuff like json.
Its key difference with TextQL and similar alternatives is it works on streams instead of importing everything in a SQLite then querying it. It seems strange to read a whole file in memory then perform a `SELECT` query on it when you could just run that query while reading the file. That means a much lower memory footprint and faster execution, but on the other hand you can only use the subset of SQL that’s implemented.
[1] https://gallery.technet.microsoft.com/office/Log-Parser-Stud...
.mode csv
.headers on
.import my.csv tablename
This does look extremely convenient, though; being able to use UNIX pipes will be a huge improvement to my workflow.[0] http://bigbash.it or the corresponding Github repo.
[1] https://jsvine.github.io/intro-to-visidata/
[2] Previous HN VisiData thread https://news.ycombinator.com/item?id=16515299
Plus you can access all this programmatically and not just through the dbish command. Since this is a central part of Perl infrastructure, there are a ton of tools that extend the DBI, from a variety of ORMs like DBIx::Class, to data export and even DDL delta management.
Generalized Database Interface: https://metacpan.org/pod/DBI DBI Shell program: https://metacpan.org/pod/DBI::Shell CSV driver: https://metacpan.org/pod/DBD::CSV
ps aux | tail -n +2 | awk '{ printf("%s\t%s\n", $1, $4) }' | \
clickhouse-local -S "user String, mem Float64" \
-q "SELECT user, round(sum(mem), 2) as memTotal FROM table GROUP BY user ORDER BY memTotal DESC FORMAT Pretty"
┏━━━━━━━━━━┳━━━━━━━━━━┓
┃ user ┃ memTotal ┃
┡━━━━━━━━━━╇━━━━━━━━━━┩
│ clickho+ │ 0.7 │
├──────────┼──────────┤
│ root │ 0.2 │
├──────────┼──────────┤
│ netdata │ 0.1 │
├──────────┼──────────┤
│ ntp │ 0 │
├──────────┼──────────┤
│ dbus │ 0 │
├──────────┼──────────┤
│ nginx │ 0 │
├──────────┼──────────┤
│ polkitd │ 0 │
├──────────┼──────────┤
│ nscd │ 0 │
├──────────┼──────────┤
│ postfix │ 0 │
└──────────┴──────────┘
Has the advantage of being really fast. $ ps aux | sqawk -output table \
'select user, round(sum("%mem"), 2) as memtotal
from a
group by user
order by memtotal desc' \
header=1
┌────────┬────┐
│dbohdan │67.1│
├────────┼────┤
│ root │3.5 │
├────────┼────┤
│ avahi │0.0 │
├────────┼────┤
│ daemon │0.0 │
├────────┼────┤
│message+│0.0 │
├────────┼────┤
│ nobody │0.0 │
├────────┼────┤
│ ntp │0.0 │
├────────┼────┤
│ rtkit │0.0 │
├────────┼────┤
│ syslog │0.0 │
├────────┼────┤
│ uuidd │0.0 │
├────────┼────┤
│whoopsie│0.0 │
└────────┴────┘
Link: https://github.com/dbohdan/sqawkJust for historical interest, similar things have been done before.
e.g.http://quisp.sourceforge.net/shsqlhome.html
See also Facebook's osquery of course. Turns even complex structures into sql tables -- helped by Augeas.net.
[1] https://www.lnav.org -- a feature-rich, powerful, flexible "mini-ETL" with an embedded sqlite engine -- is one of my all-time favorite CLI tools that somehow remains under the radar
CREATE EXTENSION file_fdw;
CREATE SERVER import FOREIGN DATA WRAPPER file_fdw;
CREATE FOREIGN TABLE foo (
col1 text,
col2 text,
...
) SERVER import
OPTIONS ( filename '/path/to/foo.csv', format 'csv' );
SELECT col1 FROM foo WHERE col2='x';I personally have been using harelba’s q (the un-googleable utility), which is just fine.
It would be great not to shift gears into SQLite syntax and date formatting all the time. Does anyone know of a similar tool that runs over postgres?
That sounds like [lnav](https://www.lnav.org).
For queries, it does use SQLite under the hood, but before querying your "arbitrary text data" files, you can use regex to define a custom format (eg with named groups and back references), providing structure against which standard SQL is an ideal tool to query.
It's simpler than I'm probably making it sound. Highly recommended.
https://github.com/jeroenjanssens/data-science-at-the-comman...
I was not able to commit its options to long term memory, so I've built a bash script that contains a pipe of commands, including Rio.
#!/usr/bin/env Rscript
library(sqldf, quietly=TRUE)
statement <- commandArgs(TRUE)
a <- read.table(file("stdin"), header=TRUE)
print(sqldf(statement))
then we can call ps -Ao user | Rsql 'select USER, count(*) as nprocesses from a group by USER limit 5'
to get the output USER nprocesses
1 avahi 2
2 colord 1
3 daemon 1
4 marcle 136
5 messagebus 1But, there certainly are good reasons for using SQL in R. Packages like sqldf exist, so their authors would probably be able to give the best answer to your question.
Some reasons:
- SQL is a very widely-known DSL for working with tabular data, so it may make sense to make that interface available within R.
- For certain operations (e.g. specific types of joins) it may be more natural / easier to express the operation in SQL.
- For large data sets, some operations in R have large memory footprints, and doing the operations in a database may have lower memory requirements.
sqlite> .import myfile.csv mytable
sqlite> select ...
What does this tool give you that SQLite doesn't do out of the box?> sqlite import will not accept stdin, breaking unix pipes. textql will happily do so.
> textql supports quote escaped delimiters, sqlite does not.
> textql leverages the sqlite in memory database feature as much as possible and only touches disk if asked.
#!/usr/bin/env rc
row_headers=''
output_mode=column
fn usage {
echo $0 usage
echo -o <sqlite output mode> '#' which output mode to use
echo -r '#' if present, output row headers
echo -h '#' this message
}
while(~ $1 -*) {
switch($1) {
case -o
output_mode=$2
shift
case -r
row_headers='.headers on'
case -h
usage
exit 0
case *
echo Bad args: $*
usage
exit 1
}
shift
}
test $#* -ne 1 && echo Wrong number of arguments && usage && exit 1
sql_statement=$1
sqlite_bin=''
{ which sqlite > /dev/null >[2=1] && sqlite_bin=sqlite } || { which sqlite3 >/dev/null >[2=1] && sqlite_bin=sqlite3 }
table_name=atable
stdin_file=/proc/$pid/fd/0
{
echo .mode csv
echo .import $stdin_file $table_name
echo $row_headers
echo .mode $output_mode
echo $sql_statement
} | $sqlite_binKey differences between textql and sqlite importing
sqlite import will not accept stdin, breaking unix pipes. textql will happily do so.
textql supports quote escaped delimiters, sqlite does not.
textql leverages the sqlite in memory database feature as much as possible and only touches disk if asked.
I don't think OP needs to pussy foot around some stranger on an internet message board. It's free shit.
The Readme is describing the differences in importing. I'm not sure how your distinction makes this any more clear.
It looks like textql loads everything into an in-memory SQLite instance, whereas I'd really like to see an approach that uses the SQLite's virtual table mechanism (https://sqlite.org/vtab.html), which would avoid the loading step and perhaps make streaming processing possible.
The streaming would make it memory efficient, and possibly able to handle some big data - maybe not true "Big Data", but certainly 10s of gigabytes.
Anyone want to take this idea into a GoFundMe site?
Projection (mapping), a join against a fully loaded other side as well as filtering work.
Aggregation can consume an indefinite stream with limited working set if the cardinality of the grouping key isn't large.
And of course you can combine these in nested and unioned operations, computing across multiple indefinite streams concurrently and with limited working set.
It would be tricky to make work effecively without hinting for things like joins, for sure; join order is one of the hardest bits a query engine optimizes.
I usually have to develop a database in Windows and Access. One more tool to work in Linux is a good idea.
I used to use awk and sed before.