using let blocks in orientdb select statements - orientdb

Hopefully a quick one - I'm struggling to make a let statement work.
I have a database of People vertexes. The vertexes have ident fields and name fields. This query returns one row - a person named Bob.
select from Person where ident = 1
I want to return all rows with the same name as this person. There are two Bobs in the data (as proof, the following query returns two rows):
select from Person where name = 'Bob'
I think all of the following queries should return those same two rows, but they all return 0 rows. They all involve different ways of using a let statement. Can anyone see what I'm doing wrong?
select name from Person
let $tmp = (select from Person where ident = 1)
where name = $tmp.name
select name from Person
let $tmp = (select name from Person where ident = 1)
where name = $tmp
select name from Person
let $tmp = 'Bob'
where name = $tmp

$tmp will be a list of records, so you are asking to compare a string to a list, and it isn't working. You could do the following;
select name from Person
let $tmp = (select from Person where ident = 1)
where name = first($tmp).name
That wont return Person records though (only rows of names). Limiting the $tmp query will also improve the performance slightly. So the following is better;
select from Person
let $tmp = (select from Person where ident = 1 limit 1)
where name = first($tmp).name
But actually, using the let clause in this manner is not good. The docs say
The LET block contains the list of context variables to assign each
time a record is evaluated.
So it is* (*should be) better to rearrange your query entirely;
select expand($persons_with_name) let
$person_with_ident = first((select from Person where ident = 1 limit 1)),
$persons_with_name = (select from Person where name = $parent.$person_with_ident.name)

You can look if name is contained in $tmp
select name from Person
let $tmp = (select name from Person where ident = 1)
where name in $tmp
or if $tmp contains name
select name from Person
let $tmp = (select name from Person where ident = 1)
where $tmp contains name

Related

Update a column using the value of another column per row

I'm trying to update a value in one table based on the value of another table in a one-to-many relationship, where there will be one movie but many reviews
Here's the schema for my tables
movie
+----+-------------+------+
| id | reviewCount |score |
+----+-------------+------+
review
+--------+---------+-------+
| userId | movieId | score |
+--------+---------+-------+
And here's the query I'm trying to run
UPDATE movie
SET score =
CASE
WHEN m."reviewCount" = 1
THEN 0
ELSE ((m.score * m."reviewCount") - r.score) / (m."reviewCount" - 1)
END,
"reviewCount" = m."reviewCount" - 1
FROM movie AS m INNER JOIN (
SELECT "userId", "movieId", score
FROM review) r
ON m.id = r."movieId"
WHERE r."userId" = $1;
However, when I run it, I get the same value across all my rows rather than accounting for the score of each review. Is there something I'm doing wrong or a better way to run this query?
As documented in the manual you should not repeat the target table of an UPDATE in the FROM clause.
There is also no need for a derived table ("sub-query") to get the values from the review table:
UPDATE movie m
SET score = CASE
WHEN m."reviewCount" = 1 THEN 0
ELSE ((m.score * m."reviewCount") - r.score) / (m."reviewCount" - 1)
END,
"reviewCount" = m."reviewCount" - 1
FROM review r
WHERE m.id = r."movieId" --<< this is the join between the two tables
AND r."userId" = $1;
This assumes that each user only reviews each movie once (i.e. one row per userid/movied combination in the review table). If that is not the case, the outcome is not predictable.
Last line should have
ON m.id = r."movieId"
WHERE movie.id = r."movieId" AND r."userId" = $1;
rather than m.id = r."movieId"

PostsgreSQL. How to return the number of records in the users table who have name Latifah, Elizabeth or Diana?

I have this :
SELECT count(*) FROM users
WHERE name = 'Latifah'
AND name = 'Elizabeth'
AND name = 'Diana';
It returns zero. What's wrong? Is there a way to make it shorter?
you can "aggregate" ORs to IN operator:
SELECT count(*)
FROM users
WHERE name IN ('Latifah','Elizabeth','Diana');
This is also worked:
SELECT count(*) FROM users
WHERE name = 'Latifah'
or name = 'Elizabeth'
or name= 'Diana';

Orientdb(2.1.8) Intersect function is not working

I am qorking on OrientDB(2.1.8) database and executing the below query with OrientDB functions (unionall & intersection).
There are userunits of various users, So i want to display the results if atleast one userUnits of two users(#rid=#16:2131,#rid=#16:2130) intersect then result should be displayed.
Suppose user #16:2131 userUnits are [admin,manager]
and user #16:2131 userUnits are [admin] only
so 'admin' userUnits are common so results should be displayed
but Intersect command is not working.
my below query is working fine with "unionall" function but not working with "intersect".
SELECT expand(unionall($a, $b))
LET $a = (SELECT userUnits FROM #16:2131),
$b = (SELECT userUnits FROM #16:2130)
output comes-->
admin,manager
supervisor
But when i run my query with intersect function then neither it is showing me any error nor the display results.
SELECT expand(intersect($a, $b))
LET $a = (SELECT userUnits FROM #16:2131),
$b = (SELECT userUnits FROM #16:2130)
You can try this:
SELECT intersect($a.userUnits, $b.userUnits)
LET $a = (SELECT userUnits FROM #16:2131),
$b = (SELECT userUnits FROM #16:2130)
I hope it helps
Bye

Selecting parent records by filtering multiple fields of collection of links

I have been trying to figure out this for a couple of days know but I can't come up with a query that gives me the correct results. The essence of the task is that I am trying to retrieve all the nodes of a graph that have children with attributes that satisfy multiple constraints. The issue I have is that a node may have multiple linked nodes and when I try to apply criteria to restrict which nodes must be returned by the query the criteria need to be imposed against sets of nodes instead of individual nodes.
Let me explain the problem in more detail through an example. Here is a sample schema of companies and locations. Each company can have multiple locations.
create class company extends V;
create property company.name STRING;
create class location extends V;
create property location.name STRING;
create property location.type INTEGER;
create property location.inactive STRING;
Let me now create a couple of records to illustrate the problem I have.
create vertex company set name = 'Company1';
create vertex location set name = 'Location1', type = 5;
create vertex location set name = 'Location2', type = 7;
create edge from (select from company where name = 'Company1') to (select from location where name in ['Location1', 'Location2']);
create vertex company set name = 'Company2';
create vertex location set name = 'Location3', type = 6;
create vertex location set name = 'Location4', type = 5, inactive = 'Y';
create edge from (select from company where name = 'Company2') to (select from location where name in ['Location3','Location4']);
I want to retrieve all companies that either don't have a location of type 5 or have a location of type 5 that is inactive (inactive = 'Y'). The query that I tried initially is shown below. It doesn't work because the $loc.type is evaluated against a collection of values instead of a individual record so the is null is not applied against the individual field 'inactive' of each location record but against the collection of values of the field 'inactive' for each parent record. I tried sub-queries, the set function, append and so on but I can't get it to work.
select from company let loc = out() where $loc.type not contains 5 or ($loc.type contains 5 and $loc.type is null)
You can try with this query:
select expand($c)
let $a = ( select expand(out) from E where out.#class = "company" and in.#class="location" and in.type = 5 and in.inactive = "Y" ),
$b = ( select from company where 5 not in out("E").type ),
$c = unionAll($a,$b)
UPDATE
I have created this graph
You can use this query
select expand($f)
let $a = ( select from E where out.#class = "company" and in.#class="location" ),
$b = ( select expand(out) from $a where in.type = 5 and in.inactive = "Y"),
$c = ( select expand(out) from $a where in.type = 5 and in.inactive is null),
$d = difference($b,$c),
$e = ( select from company where 5 not in out("E").type ),
$f = unionAll($d,$e)
Hope it helps.
Try this query:
select expand($d) from company
let $a=(select from company where out().type <> 5 and name contains $parent.current.name),
$b=(select from company where out().type contains 5 and name=$parent.current.name),
$c=(select from company where out().inactive contains "Y" and name=$parent.current.name),
$d=unionall($a,intersect($b,$c))
Hope it helps,
Regards,
Michela

How to join the tables in linq to sql?

Table1 :
userid name address
1 venkat srinagr
2 venkatesh sainagar
Table2:
id userid lat lon
1 1 14.000 15.000
2 2 14.3526 15.3698
by passing "venkat" as parameter then need to pull all matching records and his userid,name,lat,lon.
in above table1 "venkat" contains in both rows then need to pull 2 records.how to get userid,name,lat,lon for all matching rows..
for sigle record i am able to get.but there are multiple rows how to get please tell me....
var result = from p in cxt.Table2
where p.Table1.Name.Contains(name)
select new
{
p.Users.User_Id,p.Users.Name,p.Latitude,p.Longitude
};
Im sure someone will say this is not the most effective way but this is how i would do it.
string InputString = "venkat";
var tab =(from a in db.tablea
from b in db.tableb
where a.userid == b.userid && a.name == InputString
select new
{
UserID = a.userid,
Username = a.name,
Latitude = b.lat,
Longditude = b.lon
}).FirstOrDefault();
FirstOrDefault() is only if you want to force only one output or null,
if you want a collection of some sort, then just remove it.