SQLITE Select results into a string - sqlite

I am looking for a method to return the results of an SQLite query as a single string for use in an internal trigger.
Something like Python's 'somestring'.join() method.
Table: foo
id | name
1 | "foo"
2 | "bar"
3 | "bro"
Then a select statement:
MAGIC_STRING_CONCAT_FUNCTION(SELECT id FROM foo,",");
To return
"1,2,3"

You're looking for the group_concat function:
group_concat((SELECT id FROM foo), ",");
The following is the description of the function group_concat from the documentation:
group_concat(X) group_concat(X,Y)
The group_concat() function returns a string which is the
concatenation of all non-NULL values of X. If parameter Y is present
then it is used as the separator between instances of X. A comma (",")
is used as the separator if Y is omitted. The order of the
concatenated elements is arbitrary.

Related

Extract a regex capture group from a string in MariaDB

For example:
Regex: District ([0-9]{1,2})([^0-9]|$)
Input District 12 2021 returns 12
Input Southern District 3 returns 3
Input FooBar returns NULL
The function REGEXP_SUBSTR doesn't allow extracting a single capturing group.
You can use e.g. REGEXP_REPLACE(input, regex, '\\1') to replace occurrences of regex in input with the first capture group of regex.
The following stored function makes this easy to use:
DELIMITER $$
CREATE FUNCTION regexp_extract(inp TEXT, regex TEXT, capture INT) RETURNS TEXT DETERMINISTIC
BEGIN
DECLARE capstr VARCHAR(5);
DECLARE mregex TEXT;
IF inp IS NULL OR LENGTH(inp) = 0 OR inp NOT REGEXP regex THEN
RETURN NULL;
END IF;
SET capstr = CONCAT('\\', capture);
SET mregex = CONCAT('.*', regex, '.*'); -- Want to match the entire input string so it all gets replaced
RETURN REGEXP_REPLACE(inp, mregex, capstr);
END;
$$
DELIMITER ;
Used like so:
SELECT regexp_extract('District 12 2021', 'District ([0-9]{1,2})([^0-9]|$)', 1);
For those users who might be stuck with an earlier version of MySQL or MariaDB which does not have REGEXP_REPLACE available, we can also use SUBSTRING_INDEX here:
SELECT SUBSTRING_INDEX(
SUBSTRING_INDEX('Southern District 3', 'District ', -1), ' ', 1); -- 3

Kusto result column name, bin value from request_parameters

Using query_parameters, how can I:
specify a result column name (ex: summarize ResultColumnName = count())
specify the value of a bin, when value is actually the name of a column in the table
This is easiest to summarize with an example:
let myTable = datatable (Timestamp:datetime)
[datetime(1910-06-11),
datetime(1930-01-01),
datetime(1997-06-25),
datetime(1997-06-25)];
let UntrustedUserInput_ColumnName = "MyCount"; // actually from query_parameters
let UntrustedUserInput_BinValue = "Timestamp"; // actually from query_parameters
let UntrustedUserInput_BinRoundTo = "365d"; // actually from query_parameters
// the query I really want to perform
myTable
| summarize MyCount=count() by bin(todatetime(Timestamp), totimespan(365d));
// what the query looks like if I use query_parameters
myTable
| summarize UntrustedUserInput_ColumnName=count() by bin(todatetime(UntrustedUserInput_BinValue), totimespan(UntrustedUserInput_BinRoundTo));
Results:
Timestamp MyCount
--------- -------
1909-09-26T00:00:00Z 1
1929-09-21T00:00:00Z 1
1996-09-04T00:00:00Z 2
Column1 UntrustedUserInput_ColumnName
------- -----------------------------
4
I can't find a solution to #1.
It appears #2 can almost be solved by using column_ifexists, but I don't have a "default" to fall back on, I'd rather just fail if the column doesn't exist.
Treating column names as variables is not possible since columns names are part of the result schema coming out of each operator (with the exception of the "evaluate" operator, see specifically the pivot plugin).
There actually is a way to set variable names to a column, using a hacky trick:
let VariableColumnName = "TestColumn"; // the new column name that you want
range i from 1 to 5 step 1 // this is just a sample query
| project pack(VariableColumnName, i) // this created a JSON
| evaluate bag_unpack(Column1) // unpacking the JSON creates a column with a dynamic name
This will return a column named TestColumn, which is set in VariableColumnName.

Converting a string to be used in in-clause Teradata

I have a string like this ('car, bus, train')
I want to convert it to be used in an in-clause. Basically I want to convert it to
('car','bus','train'). Please how do I do this in Teradata
I don't know how you are getting data like that, but if you have no control over that, you can use STRTOK_SPLIT_TO_TABLE.
select t.* from table (strtok_split_to_table(1,'car, bus, train',',')
returns (outkey integer,tokennum integer,resultstring varchar(25))) as t
Run by itself, that gives you:
outkey tokennum resultstring
1 1 car
1 2 bus
1 3 train
You can use that as a derived table and join it to the table you want to filter by. Something like:
select
<your table>.*
from
<your table>
inner join (select t.* from table (strtok_split_to_table(1,'car, bus, train',',')
returns (outkey integer,tokennum integer,resultstring varchar(25))) as t) dt
on yourtable.yourcolumn = dt.resultstring
here is the another way of spliting the input for n number of commas and use IN clause.
SELECT regexp_substr('car,bus,train','[^,]+',1,day_of_calendar) fields
FROM sys_calendar.calendar
WHERE day_of_calendar <= (CHAR('car,bus,train') - CHAR(oreplace('car,bus,train',',','')))+1;
Output of the Query
fields
~~~~~~~~
bus
car
train
Here is the systax to use in where clause
SELECT * FROM <your table>
WHERE yourtable.requiredColumn in
(
SELECT regexp_substr('car,bus,train','[^,]+',1,day_of_calendar) fields
FROM sys_calendar.calendar
WHERE
day_of_calendar <= (CHAR('car,bus,train') - CHAR(oreplace('car,bus,train',',','')))+1
);
Basically what we are doing here is splitting the string for each comma and below function is calculating number of commas in the string
(CHAR('car,bus,train') - CHAR(oreplace('car,bus,train',',','')))+1

sqlite advanced case sensitive query

i search for a special kind of query in SQLite
to sort a notes table.
The result from the query should be like this:
id oid
1 1
2 1,1
5 1,1,a
6 1,1,a,1
3 1,1,A
4 1,1,A,1
But with the folling code I receive this:
CREATE TABLE note (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created DATETIME DEFAULT CURRENT_TIMESTAMP,
oid VARCHAR unique,
tit VARCHAR,
dsc VARCHAR
);
select id, oid from note
order by oid collate NOCASE
Result:
id oid
1 1
2 1,1
5 1,1,a
3 1,1,A
6 1,1,a,1
4 1,1,A,1
Any suggestions?
Thanks
--jonah
The following transforms the sort keys so that the normal case sensitive ordering yields the requested result:
If there was a togglecase() function, the function would uppercase lowercase and lowercase uppercase (for example Hello => hELLO), one could ORDER BY togglecase(oid) and the result would be in the order requested.
You could define such a function and expose it to SQLite as a UDF. It could also be possible to write this function using builtin SQLite functions but I don't know them well enough to give an answer using them. The following is an example of such a function in Python:
def togglecase(s):
def toggle(l):
if l.isupper():
return l.lower()
if l.islower():
return l.upper()
return l
return ''.join(toggle(l)
for l in s)
Note that for proper Unicode support it needs to iterate over graphemes. Not over code points.
See that this does what I described it to do:
>>> togglecase("1,1,A")
'1,1,a'
>>> togglecase("1,1,a")
'1,1,A'
It is possible to test if this sorts correctly in Python:
>>> sorted(["1", "1,1", "1,1,a", "1,1,a,1", "1,1,A", "1,1,A,1"])
['1', '1,1', '1,1,A', '1,1,A,1', '1,1,a', '1,1,a,1']
See how the uppercase follows the lowercase:
>> sorted(["1", "1,1", "1,1,a", "1,1,a,1", "1,1,A", "1,1,A,1"], key=togglecase)
['1', '1,1', '1,1,a', '1,1,a,1', '1,1,A', '1,1,A,1']
Now if you use it in SQLite like:
SELECT id, oid
FROM note
ORDER BY togglecase(oid)
This should result in:
1 "1"
2 "1,1"
3 "1,1,a"
4 "1,1,a,1"
5 "1,1,A"
6 "1,1,A,1"
The code is untested except for the togglecase function.
You are getting that result because the sorting is pecified to be NOCASE. That means that "a" and "A" are equals. So, first the rows with "a/A" and nothing after, and then rows with "a/A" and data after.
If you make the query CASE SENSITIVE, you will get a different result. BUT "A" comes befores "a" in case sensitive sort:
SELECT id, oid
FROM note
ORDER by oid
Results:
1 "1"
2 "1,1"
5 "1,1,A"
6 "1,1,A,1"
3 "1,1,a"
4 "1,1,a,1"

sqlite returns 0 rows

SELECT skill_name, character_name, cb_id, cb_id2 FROM characterbasics, characterskills WHERE characterbasics.character_name = 'Joe' & characterbasics.cb_id = characterskills.cb_id2
This, for some reason, returns 0 rows
The character name is in there (as well as 2 other dummy names).. and both cbid and cbid2 are the same.
When i try the query without the & cbid=cbid2 i get the name with the other data.. now when i check for JUST cbid=cbid2 i get 3 different dummy characters i created...
im trying to pull all "skills" associated with one character by matching the id of the character name in table 1 with the character id in table 2
Where have I erred?
cn = character name
cn cbid cbid2
Joe 2 2
This is what it SHOULD look like..
You cant use & as logical AND operator (& is binary operator), so sql should look like :
SELECT skill_name, character_name, cb_id, cb_id2
FROM characterbasics, characterskills
WHERE characterbasics.character_name = 'Joe' AND characterbasics.cb_id = characterskills.cb_id2

Resources