Use ARRAY_CONTAINS with a select statement - azure-cosmosdb

I have a query which nearly returns the data I need:
SELECT *
FROM a in c.Things
WHERE ARRAY_CONTAINS(['ThingA', 'ThingB'], a.Name)
The problem is that the array ['ThingA', 'ThingB'] can't be hard-coded, as the values in the array should by dynamically generated based off some query. For this example, that query is this:
select VALUE ARRAY (
SELECT VALUE a.Name
FROM a in c.Things
where a.Visible)
from c
WHERE c.Discriminator='Type'
Which returns something like: ['ThingOne', 'ThingTwo']
Is it possible to include a query inside ARRAY_CONTAINS like this:
SELECT *
FROM a in c.Attributes
WHERE ARRAY_CONTAINS(
( select VALUE ARRAY(
SELECT VALUE a.Name
FROM a in c.Things
where a.Visible)
from c
WHERE c.Discriminator='Type'
)
, a.Name)
If I run this in Cosmos DB Studio I get this error:
Microsoft.Azure.Cosmos.Query.Core.Exceptions.ExpectedQueryPartitionProviderException: {"errors":[{"severity":"Error","location":{"start":147,"end":148},"code":"SC2001","message":"Identifier 'c' could not be resolved."}

If I understand correctly, your inner query is independent of the outer query, so what you want is an uncorrelated subquery. This is not supported in Cosmos DB; the documentation says:
Azure Cosmos DB supports only correlated subqueries.

Related

Returning array from complex documents

I am trying to get an array of id's into an array of strings and not objects.
Folowing query works:
SELECT * FROM c.id
Returns:
[
"92226d610a1047ecb207c98f845bde14",
"3936d9172f8c4bfd891a91457935f1ac",
"ab466a79f1b44fc99c0f2fcefbec0aa2",
"0d5254279e02430ba8f09afbbd6f2259",
"b768a932ac9042f096557eea3ad5bc4e",
"6917916a41724249a1ae85963f46d58d",
"593ff8f0ceab4b2c8279d77b270307e4"]
However when I add a where clause it fails:
SELECT * FROM c.id where c.vesselId="6c0f3e571b0f4e3bb96f82e6b08d8d36"
What is the best approach to get an array with a where clause?
You can use distinct value clause to derive ids as array.
select distinct value c.id from c where c.vesselId ='6c0f3e571b0f4e3bb96f82e6b08d8d36'

Subquery with alias in SQLite

I have a query that I run in PostgreSQL like this:
select
c_count, count(*) as custdist
from (
select
c_custkey,
count(o_orderkey)
from
customer left outer join orders on
c_custkey = o_custkey
and o_comment not like '%special%requests%'
group by
c_custkey
)as c_orders (c_custkey, c_count)
group by
c_count
order by
custdist desc,
c_count desc;
And I wanted to run it on SQLite, but I got this error: Error: near" (": syntax error. Maybe he doesn't recognize this as c_orders (c_custkey, c_count).
Is there any way to rewrite this query to execute in SQLite?
SQLite does not allow redefining/renaming columns for an nested, aliased query. You can do that with a WITH clause (i.e. Common Table Expression; CTE). Or you can add aliases to the nested query columns directly using AS keyword.
Interesting that this is exactly how the outer query columns are named. Just use the same pattern for the nested query. I don't use PostgreSQL, but why not add aliases directly on each column and complicate it by using different syntax for each part of the query?
select
c_count, count(*) as custdist
from (
select
c_custkey,
count(o_orderkey) AS c_count
from
customer left outer join orders on
c_custkey = o_custkey
and o_comment not like '%special%requests%'
group by
c_custkey
) AS c_orders
group by
c_count
order by
custdist desc,
c_count desc;

selecting only max clause without group by properties in subquery using Nhibernate

I have SQL query like this:
select * from dbo.table1 where Id in
(
select max(id) as id from dbo.table1 group by prop1, prop2, prop3
)
I want to create NHibernate query which is be able to do this for me. I tried to use QueryOver but it doesn't work. Do you have any suggestions how to do it?
NHibernate supports even this kind of queries. Please, see more in documentation: 15.8. Detached queries and subqueries. We just have to split the query (as in your SQL snippet) into two parts:
inner select
the select with the IN clause
Let's assume, that the dbo.table1 in the Questin is mapped into MyEntity.
To create inner select, let's use the DetachedCriteria
EDIT (extended with the Group by, SqlGroupProjection)
There is an extract of the SqlGroupProjection method:
A grouping SQL projection, specifying both select clause and group by
clause fragments
// inner select
DetachedCriteria innerSelect = DetachedCriteria
.For(typeof(MyEntity))
.SetProjection(
Projections.ProjectionList()
.Add(
Projections.SqlGroupProjection(
" MAX(ID) ", // SELECT ... max(ID) only
" Prop1, Prop2, Prop3", // GROUP BY ... property1, p2...
new string[] {"ID"}, // could be empty, while not used for
new IType[] { NHibernate.NHibernateUtil.Int32 } // transformation
)
)
;
Note: I've provided even the last two paramters, but in this case they could be empty: new string[], new IType[] {}. These are used only for Transformation (materialization from data into entity). And this is not the case, we are just building inner select...
// the select with IN clause
var result = session.CreateCriteria(typeof(MyEntity))
.Add(Subqueries.PropertyIn("ID", innerSelect))
.List<MyEntity>();
Also related could be 15.7. Projections, aggregation and grouping

dynamic table name in a query

How can I put a table name dynamically in a query?
Suppose I have a query as shown below:
Select a.amount
,b.sal
,a.name
,b.address
from alloc a
,part b
where a.id=b.id;
In the above query I want to use a table dynamically (part b if the database is internal, p_part b if the database if external).
I have a function that returns which database it is. Suppose the function is getdatabase();
select decode(getdatabase(),'internal','part b','external','p_part b')
from dual;
How can I use this function in my main query to insert the table name dynamically into the query?
I don't want to implement this using the primitive way of by appending strings to make a final query and then open cursor with that string.
I don't want to implement this with primitive way of by appending
strings to make a final query and then open cursor with that string .
That's really the only way you can do it. It's not possible to use a variable or function call for the table name when using a regular PL/SQL SQL block, you have to use dynamic SQL.
Refer to Oracle documentation for more details:
http://docs.oracle.com/cd/B10500_01/appdev.920/a96590/adg09dyn.htm
Here's an example from the doc:
EXECUTE IMMEDIATE 'SELECT d.id, e.name
FROM dept_new d, TABLE(d.emps) e -- not allowed in static SQL
-- in PL/SQL
WHERE e.id = 1'
INTO deptid, ename;
You can do this without dynamic SQL, assuming both tables (part and p_part) are available at compile time:
select a.amount
,b.sal
,a.name
,b.address
from alloc a
,part b
where a.id=b.id
and (select getdatabase() from dual) = 'internal'
UNION ALL
select a.amount
,b.sal
,a.name
,b.address
from alloc a
,p_part b
where a.id=b.id
and (select getdatabase() from dual) = 'external'
;
I've put the function call in a subquery so that it is run only once per call (i.e. twice, in this instance).

In query in SQLite

"IN" query is not working. Please guide me if i am wrong.
KaizenResultsInformationTable is MasterTable having field "recordinfo", this field contains Child table Ids as string.
kaizenResultsRecordInformationTable is Childtable having field "recordId".
I have to match records of child.
Query:
select recordinfo from KaizenResultsInformationTable
Output: ;0;1;2;3;4;5;6;7;8;9;10
Query:
select substr(replace(recordinfo,';','","'),3,length(recordinfo))
from KaizenResultsInformationTable`
Output: "0","1","2","3","4","5"
This query is not working:
select * from kaizenResultsRecordInformationTable
where substr(recordid,0,2) in (
select substr(replace(recordinfo,';','","'),3,length(recordinfo))
from KaizenResultsInformationTable
)
This query is working:
select * from kaizenResultsRecordInformationTable
where substr(recordid,0,2) in ("0","1","2","3","4","5")
You can't use in like that. In your second query, you are passing in a single string containing a comma-separated list of values.
It is better to represent a list of IDs as one record for each value.
Also, I'm not sure why you are taking a substring of your recordid. You should usually be storing one value per column.
However, if you can't change the schema, you can use string matching with 'like' instead of 'in'. Something like this should work:
select a.* from kaizenResultsRecordInformationTable a
join KaizenResultsInformationTable b
on (';'+b.recordinfo+';') LIKE ('%;'+trim(substr(recordid,0,2))+';%')
So if your recordinfo looks like 1;2;3;4;5;6, and your substr(recordid,0,2) looks like 1, this will include that row if ";1;2;3;4;5;6;" LIKE "%;1;%", which is true.

Resources