How to exclude some records in string in kdb? - kdb

I would like to exclude some records from the table.
a:("abc*";"eeee*")
tab:([]cola:("abcdef";"bcdefgh";"tttttt");colb:`a`b`c)
it works if I would like only certain records:
eg.
raze {select from tab where cola like x } each a
output:
cola colb
-------------
"abcdef" a
Now I want to exclude the record above by running the following command
raze {select from tab where not cola like x } each a
But it returns
cola colb
--------------
"bcdefgh" b
"tttttt" c
"abcdef" a
"bcdefgh" b
"tttttt" c
I would like it to return this:
cola colb
--------------
"bcdefgh" b
"tttttt" c

Does this work?
q)select from tab where not any cola like/: a
cola colb
--------------
"bcdefgh" b
"tttttt" c
Edit: Why do we need an any?
If you index into the table with the column name to get the column as an array, it's easier to see:
q)tab[`cola]
"abcdef"
"bcdefgh"
"tttttt"
q)tab[`cola] like/: a
100b
000b
q)any tab[`cola] like/: a
100b
q)not any tab[`cola] like/: a
011b
When you use like with multiple strings and multiple regexes, you will get an array for each string (with the size of the array being the number of regexes). We want to see if our string matches any of the regexes, and then exclude them if they do.

Related

How to update new empty column with data that depends on mathematical operation of different data types?

[beginner]
I have a table that looks like this:
colA colB
1 <null>
2 <null>
3 <null>
colB is the new empty column I added to the table. colA is varchar and colB is double precision data type (float).
I want to update colB with a colA multiplied by 2.
New table should look like this:
colA colB
1 2
2 4
3 6
When I go to update colB like so:
update tablename set colB = colA * 2
I get error:
Invalid operation: Invalid input syntax for type numeric
Ive tried to work around this with solutions like this:
update tablename set colB = COALESCE(colA::numeric::text,'') * 2
but get the same error.
In a select statement on the same table, this works on colA which is varchar:
select colA * 2 from tablename
How can I update a column with mathematical operations with different datatype reference columns? I cant update datatype for colA.
I suppose that Laurenz Albe is correct and there are non-numeric values in col_a
So UPDATE must be guarded:
UPDATE T
SET col_b =
CASE
WHEN col_a ~'^([0-9]+\.?[0-9]*|\.[0-9]+)$' THEN col_a::numeric *2
END ;
-- or this way
UPDATE T
SET col_b = col_a::numeric *2
WHERE
col_a ~'^([0-9]+\.?[0-9]*|\.[0-9]+)$' ;
Look at fiddle: https://www.db-fiddle.com/f/4wFynf9WiEuiE499XMcsCT/1
Recipes for "isnumeric" you can get here: isnumeric() with PostgreSQL
There is a value in the string column that is not a valid number. You will have to fix the data or exclude certain rows with a WHERE condition.
If you say that running the query from your client works, that leads me to suspect that your client doesn't actually execute the whole query, but slaps a LIMIT on it (some client tools do that).
The following query will have to process all rows and should fail:
SELECT colA * 2 AS double
FROM tablename
ORDER BY double;
update tablename set colB = colA::numeric * 2

Selecting count of occurences of values in kdb

How to count occurences of distinct values from one column in another column in kdb. The idea is to return the count of values in another column.
The table looks like
Col1 : x,y,z and Col2: x,x,l
The idea is to find count of occurences of x,y,z from col1 in col2, which in above case is 2,0,0
You could try this:
tab:([]col1:`x`y`z;col2:`x`x`w)
q)exec([]distinct col1)!0^([]count each group col2)distinct col1 from tab
col1| col2
----| ----
x | 2
y | 0
z | 0
Desired value can be found as a map of Col2 occurrences. Which is later looked up by values from Col1
t: ([] Col1:`x`y`z; Col2:`x`x`l);
update Col1Col2Count: 0^(count each group Col2) Col1 from t

Delete column based on type in KDB+

I have a table with a bunch of columns of various types. I need to delete all columns of a particular type, but I can't figure out how to do this.
I would like something like this:
delete from quotes where type = 11
But this doesn't work. Is there a way to do this? I was also able to list the relevant columns with the command
select c from meta quotes where type="s"
But this gives me a one column table with the column headings and I don't know where to go from there.
Could use a functional delete (!), or a take (#) or a drop (_)
q)t:([] col1:`a`b`c;col2:1 2 3;col3:`x`y`z;col4:"foo")
q)![t;();0b;exec c from meta[t] where t="s"]
col2 col4
---------
1 f
2 o
3 o
q)(exec c from meta[t] where t<>"s")#t
col2 col4
---------
1 f
2 o
3 o
q)(exec c from meta[t] where t="s") _ t
col2 col4
---------
1 f
2 o
3 o

PostgreSQL 9.3: Split one column into multiple

I want to split one column that is colb in the given below example into two columns
like column1 and column2.
I have a table with two columns:
Example:
create table t3
(
cola varchar,
colb varchar
);
Insertion:
insert into t3 values('D1','2021to123'),
('D2','112to24201'),
('D3','51to201');
I want to split the colb values into two columns like the following expected result:
Expected Result:
cola column1 column2
---------------------------------
D1 2021 123
D2 112 24201
D3 51 201
select cola
,split_part(colb, 'to', 1) col1
,split_part(colb, 'to', 2) col2
from t3
Quoted from the PostgreSQL Documentation:
split_part(string text, delimiter text, field int)
Split string on delimiter and return the given field (counting from
one)

Postgres "reverse count(*)" (unnest?)

I'm trying to do what I would call a "reverse count(*)" in PostgreSQL (8.4 +). I want my output to have the exact same number of rows as the number specified in the total column for each letter...
Table 1:
letter | total
-------------
a | 3
b | 2
c | 4
d | 1
Expected table output:
letter
-----
a
a
a
b
b
c
c
c
c
d
I am unsure if and how I could use the unnest function here....
Yes - unnest is what you'll want (once you've got an array of course)
richardh=> SELECT array_fill(letter, ARRAY[total]) FROM expand;
array_fill
------------
{a,a,a}
{b,b}
{c,c,c,c}
{d}
(4 rows)
richardh=> SELECT unnest(array_fill(letter, ARRAY[total])) FROM expand;
unnest
--------
a
a
a
b
b
c
c
c
c
d
(10 rows)
Here's solution that uses a tally or numbers table instead of UNNEST. It's a fairly cross platform solution in that every database has a solution for creating a numbers table although most not as nice as postgresql.
SELECT Letter
FROM
table1
INNER JOIN generate_series(1,100) num
ON table1.total >= num
ORDER BY Letter
SQL Fiddle Demo
I hardcoded the generate_series to 100. However as Clodoado demonstrates you can use MAX(Total) in the call to Generate_series
SELECT Letter
FROM
table1
INNER JOIN
generate_series(
1,
(select max(total) from table1)
) num ON table1.total >= num
ORDER BY Letter
SQL Fiddle Demo