Using CONTAINSTABLE with a FORMSOF and asterisk - sql

I am trying to use CONTAINSTABLE with FORMSOF and searching for prefixes using the asterisk. Is this possible, and if so what is the correct syntax?
My (wrong) attempt is:
CONTAINSTABLE( abc.Table, ColumnName, 'FORMSOF( THESAURUS, "wine*" OR "vine*" )')
What do I need to change to make this valid?

CONTAINSTABLE Doesnt take table name as parameter, it will only search on columns
It should be like:
CONTAINSTABLE(ColumnName, 'FORMSOF( THESAURUS, "wine*" OR "vine*" )')

Not possible in one term. From the docs:
<simple_term> ::=
{ word | "phrase" }
<prefix term> ::=
{ "word*" | "phrase*" }
<generation_term> ::=
FORMSOF ( { INFLECTIONAL | THESAURUS } , <simple_term> [ ,...n ] )
https://learn.microsoft.com/en-us/sql/relational-databases/system-functions/containstable-transact-sql?view=sql-server-ver15
If it was combined into one term it could be quite expensive, because you're asking the DB to find all words with the substring and then find all similar words to those. In your above example it would have to do that for both wine* and vine*. Ranking might be interesting too.
One workaround is to search twice, once using prefix and once using the thesaurus, then combine the results using your own ranking approach.

CONTAINSTABLE Can take table name as parameter
CONTAINSTABLE
( table , { column_name | ( column_list ) | * } , ' <contains_search_condition> '
[ , LANGUAGE language_term]
[ , top_n_by_rank ]
)
See MS Docs

Related

Elasticsearch, Elasticsearch SQL, SHOW COLUMNS or DESCRIBE - is there a posibility to filter the output

I have simple elastic SQL query like this:
GET /_sql?format=txt
{
"query" :"""
DESCRIBE "index_name"
"""
}
and it works, and the output is like this:
column | type | mapping
-----------------------------------------------------------
column_name1 | STRUCT | object
column_name1.Id | VARCHAR | text
column_name1.Id.keyword | VARCHAR | keyword
Is there a possibility to the prepare above query using filter or where, for example something like this:
GET /_sql?format=txt
{
"query":"""
DESCRIBE "index_name"
""",
"filter": {"terms": {"type.keyword": ["STRUCT"]}}
}
or
GET /_sql?format=txt
{
"query":"""
DESCRIBE "index_name"
WHERE "type" = 'STRUCT'
"""
}
That is not possible, no.
While the DESCRIBE sql command seems to return tabular data, it is not a query and it does not support WHERE clauses or can be used within a SELECT statement. That is actually not specific to Elasticsearch, but the same in RDBMs.
The same apparently is true for the Elasticsearch filter clause. This again will work with SELECT SQL statements, but with DESCRIBE or SHOW COLUMNS - while not producing an error - it simply will have no effect on the results.
In "real" SQL, you could work around this by querying information_schema.COLUMNS, but that is not an option in Elasticsearch.

Databases that support SELECT * EXCEPT/REPLACE?

BigQuery supports the following notation for SQL:
select_list:
{ select_all | select_expression } [, ...]
select_all:
[ expression. ]*
[ EXCEPT ( column_name [, ...] ) ]
[ REPLACE ( expression [ AS ] column_name [, ...] ) ]
Meaning something like the following can be done:
SELECT * EXCEPT (id, socialSecurity)
And some other small things.
Do any databases support this? I find the EXCEPT clause useful, and although I know how to use the REPLACE I've never found an actual practical use case for that ever. Are there ever any practical uses of that (i.e., aside from made up examples in the docs)?

SQL: Expression order in SQL compare

Is the expression order relevant in a compare statement?
For example:
select * from person where name = 'John'
and
select * from person where 'John' = name
Is there another reason other than readability to have the column first instead of the value?
Most SQL database systems will have sections of their documentation that explicitly describe their syntax. I'll use SQL Servers Search Condition1, since that's my most common reference:
<search_condition> ::=
MATCH(<graph_search_pattern>) | <search_condition_without_match> | <search_condition> AND <search_condition>
<search_condition_without_match> ::=
{ [ NOT ] <predicate> | ( <search_condition_without_match> ) }
[ { AND | OR } [ NOT ] { <predicate> | ( <search_condition_without_match> ) } ]
[ ...n ]
<predicate> ::=
{ expression { = | < > | ! = | > | > = | ! > | < | < = | ! < } expression
Here, we can see that the items on both side of the = (as well as many other operators) are described as expression - that is, anything that can appear on the left can equally well appear on the right.
Compare this, for example, with IN2:
| expression [ NOT ] IN ( subquery | expression [ ,...n ] )
where we can clearly see that what's allowed on the left and right are subtly different.
It's well worth, when you have question on syntax, to consult the relevant documentation for your database product. For standard SQL, as here, just about any product's documentation will do.
1Which in turn was reached from the documentation for WHERE
2Same page as <predicate>

PostgreSQL 9.6 jsonb query using like on arrays

i need to query a jsonb table field with the normal like functions.
This is my json field
"campi":[
{
"label":"testLabel",
"valore":[
"testValore",
"testValore2"
],
"idCampo":"testID",
"idCampoTP":"testCampoID",
"proprieta":[
{
"label":"testLabel",
"idProprieta":"testProp"
}
],
"idTipoCampo":"idTipoCampoID"
},
{
"label":"testLabel2",
"valore":[
"testValore3",
"testValore4"
],
"idCampo":"testID2",
"idCampoTP":"testCampoID2",
"proprieta":[
{
"label":"testLabel2",
"idProprieta":"testProp2"
}
],
"idTipoCampo":"idTipoCampoID2"
}
]
}
Is even possibile make a query like this?
SELECT customfield from procedura WHERE customfield->'campi' #> '[{"label":"testLabel3"}]'
But with testLabel3 with like wildcards: testLabel%
Another question, is even possibile make a query for get the object(s) "campi" with a "valore" of "testValore"?
My dream query was:
SELECT customfield from procedura WHERE customfield->'campi' #> '[{"label":"testLabel%"}]'
With % as wildcard
EDIT:
I faund a way to make some simple query:
SELECT customfield FROM procedura, jsonb_array_elements(procedura.customfield #> '{campi}') obj
WHERE obj->>'idCampoTP' LIKE 'testCampoID3%' group by procedura.id;
but i cant figure how to search in valore field sub-array
EDIT:
I found this way, but to me seem a crap solution
SELECT customfield FROM procedura, jsonb_array_elements(procedura.customfield #> '{campi}') obj
WHERE obj->>'valore' LIKE '%stValore5%' group by procedura.id;
Yes it works :)
For filtering of type 'testValore' as you have already mentioned in you question
data->'campi' #> '[{"label":"testLabel3"}]';
For extracting id with valore of type 'testValore'
data->'campi' #> '[{"valore": ["testValore"]}]';

REGEXP_SUBSTR : extracting portion of string between [ ] including []

I am on Oracle 11gR2.
I am trying to extract the text between '[' and ']' including [].
ex:
select regexp_substr('select userid,username from tablename where user_id=[REQ.UID] and username=[REQD.VP.UNAME]','\[(.*)\]') from dual
Output:
[REQ.UID] and username=[REQD.VP.UNAME]
Output needed:
[REQ.UID][REQD.VP.UNAME]
Please let me know how to get the needed output.
Thanks & Regards,
Bishal
Assuming you are just going to have two occurrences of [] then the following should suffice. The ? in the .*? means that it is non-greedy so that it doesn't gobble up the last ].
select
regexp_replace('select userid,username from tablename where user_id=[REQ.UID] and username=[REQD.VP.UNAME]'
,'.*(\[.*?\]).*(\[.*?\]).*','\1\2')
from dual
;
I'm not an Oracle user, but from quick perusal of the docs, I think this should be close:
REGEXP_REPLACE('select userid,username from tablename where user_id=[REQ.UID] and username=[REQD.VP.UNAME]',
'^[^\[]*(\[[^\]]*\])[^\[]*(\[[^\]]*\])$', '\1 \2')
Which looks much nastier than it is.
Pattern is:
^[^\[]* Capture all characters up to (but not including) the first [
(\[[^\]]*\]) Capture into group 1 anything like [<not "]">]
[^\[]* Capture everything up to (nut not including) the next [
(\[[^\]]*\]) Capture into group 2 anything like [<not "]">], at the end of the string
Then the replacement is simple, just <grp 1> <grp 2>