Why does cqlsh right-align strings? - cassandra

I find that string-values displayed using cqlsh are right-aligned. Is there a reason for this? And is there a way to left-align strings?
cqlsh:test> create table test (id int, a ascii, t text, primary key(id));
cqlsh:test> insert into test (id, a, t) values (1, 'ascii', 'text');
cqlsh:test> insert into test (id, a, t) values (2, 'a', 't');
cqlsh:test> select * from test;
id | a | t
----+-------+------
1 | ascii | text
2 | a | t
(2 rows)

I think this is mostly done for aesthetic reasons, however you can change it!
cqlsh is simply a python file that uses the python-driver. You can simply change the following code in the print_formatted_result method of cqlsh:
for row in formatted_values:
line = ' | '.join(col.rjust(w, color=self.color) for (col, w) in zip(row, widths))
self.writeresult(' ' + line)
You can change col.rjust to ljust, center, etc. or you can simply change it to 'col' to print the data as is.
Example using ljust:
cqlsh:friends> select * from group_friends;
groupid | friendid | time
--------------------------------------+----------+--------
13814000-1dd2-11b2-8080-808080808080 | 1 | 123456
13814000-1dd2-11b2-8080-808080808080 | 2 | 123456
13814000-1dd2-11b2-8080-808080808080 | 4 | 123456
13814000-1dd2-11b2-8080-808080808080 | 8 | 123456
13814000-1dd2-11b2-8080-808080808080 | 22 | 123456
13814000-1dd2-11b2-8080-808080808080 | 1002 | 123456

Try using the shell's column program to align columns:
$CASSANDRA_HOME/bin/cqlsh <<EOF | grep -v '+--' | perl -pe 's{[ ]{4,}}{|}g' | column -t -s '|' | tee out.txt
select mycol1,mycol2 from mykeyspace.mytable;
EOF
Use a here document to send input to cqlsh
Removing excess spaces with your favorite regex tool (but be careful not to remove them in your data)
Align fields based on | as the separator / delimiter using the column program
(Optional) Copy the output to a txt file using tee

Related

How to combine two columns into one in Sqlite and also get the underlying value of the Foreign Key?

I want to be able to combine two columns from a table into one column then to to be able to get the actual value of the foreign keys. I can do these things individually but not together.
Following the answer below I was able to combine the two columns into one using the first sql statement below.
How to combine 2 columns into a new one in sqlite
The combining process is shown below:
+---+---+
|HT | AT|
+---+---+
|1 | 2 |
|5 | 7 |
|9 | 5 |
+---+---+
into one column as shown:
+---+
|HT |
+---+
| 1 |
| 5 |
| 9 |
| 2 |
| 7 |
| 5 |
+---+
The second SQL statement show's the actual value of each foreign key corresponding to each foreign key id. The Foreign Key Table.
+-----+------------------------+
|T_id | TN |
+-----+------------------------+
| 1 | 'Dallas Cowboys |
| 2 | 'Chicago Bears' |
| 5 | 'New England Patriots' |
| 7 | 'New York Giants' |
| 9 | 'New York Jets' |
+-----+------------------------+
sql = "SELECT * FROM (SELECT M.HT FROM M UNION SELECT M.AT FROM Match)t"
The second sql statement lets me get the foreign key values for each value in M.HT.
sql = "SELECT M.HT, T.TN FROM M INNER JOIN T ON M.HT = T.Tid WHERE strftime('%Y-%m-%d', M.ST) BETWEEN \'2015-08-01\' AND \'2016-06-30\' AND M.Comp = 6 ORDER BY M.ST"
Result of second SQL statement:
+-----+------------------------+
| HT | TN |
+-----+------------------------+
| 1 | 'Dallas Cowboys |
| 5 | 'New England Patriots' |
| 9 | 'New York Jets' |
+-----+------------------------+
But try as I might I have not been able to combine these queries!
I believe the following will work (assuming that the tables are Match and T and baring the WHERE and ORDER BY clauses for brevity/ease) :-
SELECT DISTINCT(m.ht), t.tn
FROM
(SELECT Match.HT FROM Match UNION SELECT Match.AT FROM Match) AS m
JOIN T ON t.tid = m.ht
JOIN Match ON (m.ht = Match.ht OR m.ht = Match.at)
/* WHERE and ORDER BY clauses using Match as m only has columns ht and at */
WHERE strftime('%Y-%m-%d', Match.ST)
BETWEEN \'2015-08-01\' AND \'2016-06-30\' AND Match.Comp = 6
ORDER BY Match.ST
;
Note only tested without the WHERE and ORDER BY clause.
That is using :-
DROP TABLE IF EXISTS Match;
DROP TABLE IF EXISTS T;
CREATE TABLE IF NOT EXISTS Match (ht INTEGER, at INTEGER, st TEXT DEFAULT (datetime('now')));
CREATE TABLE IF NOT EXISTS t (tid INTEGER PRIMARY KEY, tn TEXT);
INSERT INTO T (tn) VALUES('Cows'),('Bears'),('a'),('b'),('Pats'),('c'),('Giants'),('d'),('Jets');
INSERT INTO Match (ht,at) VALUES (1,2),(5,7),(9,5);
/* Directly without the Common Table Expression */
SELECT
DISTINCT(m.ht), t.tn,
Match.st /*<<<<< Added to show results of obtaining other values from Matches >>>>> */
FROM
(SELECT Match.HT FROM Match UNION SELECT Match.AT FROM Match) AS m
JOIN T ON t.tid = m.ht
JOIN Match ON (m.ht = Match.ht OR m.ht = Match.at)
/* WHERE and ORDER BY clauses here using Match */
;
Noting that limited data (just the one extra column) was used for brevity
Results in :-

CQL (Cassandra) Select only rows with Max Value on a Column

This question is essentially the same as in this post, SQL Select only rows with Max Value on a Column, except in CQL. I'm working with Cassandra 3.10 so GROUP BY is supported, but HAVING and JOIN are not.
As in the question in above link, we need to find the rows (including "content" column) in each id, with max(rev). In fact, the actual problem I'm trying to solve is to max(rev) grouping by two identifiers, id1 and id2, so ordering by id also doesn't work here.
+------+-------+-------+--------------------------------------+
| id1 | rev | id2 | content |
+------+-------+-------+------------------------------ -------+
| 1 | 1 | 1 | ... |
| 1 | 2 | 1 | ... |
| 2 | 1 | 2 | ... |
| 1 | 3 | 3 | ...
+------+-------+-------+--------------------------------------+
The SQL solutions I had for this were:
SELECT id1, id2, rev, content FROM table
GROUP BY id1, id2 HAVING rev = MAX(rev);
And
SELECT id1, id2, rev, content FROM table
WHERE rev IN
(SELECT MAX(rev) FROM table GROUP BY id1, id2)
(The second works assuming rev is unique.)
Without HAVING or JOIN, what would be a viable approach in CQL or Cassandra 3.10?

Postgres 9.4+ split an alpha numeric string into two columns

I need to deal with the following and after searching I wasn't able to find exactly what I'm looking for:
Let's say I have a column which may or may not have an alphanumeric string
SKU
-----
12345ABC
12345-Abc
12345-Ab23
12345
Which I would like to break into
SKU | BATCH
------------------
12345 | ABC
12345 | Abc
12345 | Ab23
12345 | NULL
using PostgreSQL 9.4+ I've tried the string and sub_string method's but I'm not getting the results I'm looking to achieve... any ideas?
You can use the substring function.
with a (SKU) as (values('12345ABC'), ('12345-Abc'), ('12345-Ab23'), ('12345'))
select substring(sku from '^\d+'), substring(sku from '[a-zA-Z][a-zA-Z0-9]*$') from a;
substring | substring
-----------+-----------
12345 | ABC
12345 | Abc
12345 | Ab23
12345 |
(4 rows)
You can use regexp_matches:
with a (SKU) as (values('12345ABC'), ('12345-Abc'), ('12345-Ab23'), ('12345'))
select res[1], res[2]
from (
SELECT regexp_matches(SKU, '(\d+)[^[:alnum:]]*([[:alnum:]]+)?') res
FROM a
) y;

How to align multiline values in AsciiDoc table?

I would like to dynamically generate a table with asciidoc, which could look like this :
--------------------------------------
|Text | Parameter | Value1 | Value2 |
--------------------------------------
|foo | param1 | val1 | val2 |
--------------------------------------
|bar | param2 | val3 | val4 |
| | param3 | value_ | val6 |
| | | multi_ | |
| | | 5 | |
| | param4 | val7 | val8 |
--------------------------------------
| baz | param5 | val9 | val10 |
--------------------------------------
That is, there might be multiple parameters to one text, and their
values might span multiple lines. I am looking for a way to automatically
align these. I have a program that gathers data which changes, so I can
not manually fix things.
What I currently do: I have frame and gridless nested tables in the
Parameter, Value1 and Value2 columns. The problem with this is they only align if each value does not span multiple lines.
I also tried making Parameter, Value1 and Value2 a nested table together, with grid but no frame.
It works in terms of alignment, but doesn't look very good because the grid lines do not touch the gridlines of the outer table. Adding a frame also looks dull since it emphasizes multiparameter entries.
What I really want to do is add an extra line to the outer table (no table nesting) with no horizontal line in between, if there is an extra parameter.
I can not see how to do this with AsciiDoc. Is that possible at all? Any other suggestions on how to solve this?
It turns out this is rather easy with spans (see chapter 23.5):
.Multiline values alined with spans
[cols=",,,",width="60%", options="header"]
|================
|Text | Parameter | Value1 | Value2
|foo | param1 | val1 | val2
.3+<.<|foo .3+<.<|bar | val3 | val4
| razzle bla fasel foo bar | dazzle
|bli | bla
|foo2 | param3 | val5 | val6
|================
Now all I need to do is tell my templating system (jinja2) how much rows I need to span, but that is rather a diligent but routine piece of work.
If you're using asciidoctor, there are many other options for tables including putting columns on new lines and using the metadata for the table to specify how many columns the table contains. This is the recommended way of doing tables in Asciidoctor. You can see this example and many others in the user's guide. To give an example here on SO:
[cols="2*"]
|===
|Cell in column 1, row 1
|Cell in column 2, row 1
|Cell in column 1, row 2
|Cell in column 2, row 2
|===
Asciidoctor can be a drop in replacement for the asciidoc command, though you will want to look at differences between the two.

Create table around text

I have a list of words every is on its own line. This is the first column of a table. I'd like to create second column by hand.
I'd like to use some plugin now, that will create an ASCII table around the text, so I have nice formatting (the starting letters in each column should be in one "vertical line" or I should be able to quickly move to the correct position with one shortcut).
Is there such a plugin for vim that eases editing such tables and controls the formatting?
If you just want text alignment into table format, I use this and it works well:
http://www.vim.org/scripts/script.php?script_id=294
I wrote a command line tool a few years ago which does more closely what you want:
It allows you to edit a table in CSV format:
1,my table,another field
2,my table,yet another field
Then select the block in vim, and filter it using:
'<,'>!~/scripts/tab
This then gives you:
------------------------------------
| 1 | my table | another field |
| 2 | my table | yet another field |
------------------------------------
If you want to edit the table again, you can select the whole table and repeat with untab (which is just a symlink -> tab) which converts the table back to CSV again so that you can edit.
There's also various other options:
-------------------------------------------------------------------------
| Command/Option | Purpose |
|----------------|------------------------------------------------------|
| tab | Reads from stdin and tabulates comma seperated input |
| tab <-t> | Tabulates input and assumes first row are titles |
| tab <-h> | Prints this help |
| tab <-nb> | Tabulates without a border |
| tab <-fw X> | Wrap fields greater than X big don't break words |
| tab <-fs X> | Wrap fields greater than X big and break words |
| tab <-vp X> | Vertically pad table by X lines |
| tab <-hp X> | Horizontally pad fields by X chars |
| tab <-b X> | Tabulates with a border made from char X |
|----------------|------------------------------------------------------|
| untab | Reads from stdin and untabulates table input |
| untab <-b X> | Untabulate a table with border char X |
| untab <-nb> | Untabulate a borderless table |
-------------------------------------------------------------------------

Resources