I'm trying to do a complex querying on two tables. They look like below:
Table1:
id:
name:
table2Id:
version:
Table2:
id:
comments:
Assuming that I have the appropriate Slick classes that represents these tables, I'm trying to get all the elements from Table1 and Table 2 that satisfies the following condition:
Table1.table2Id === Table2.id and max(Table1.version)
I tried the following:
val groupById = (for {
elem1 <- table1Elems
elem2 <- table2Elems if elem1.id === elem2.id
} yield (elem1, elem2)).groupBy(_._1.id)
I know that I have to map the groupById and look for the max version, but I'm not getting the syntax right! Any help?
What I need is effectively Slick equivalent of the following SQL query:
SELECT *
FROM t t1
WHERE t1.rev = (SELECT MAX(rev) FROM t t2 WHERE t2.id = t1.id)
To simulate:
SELECT * from t t1 WHERE t1.rev = (SELECT max(rev) FROM t t2 WHERE t2.id = t1.id)
Try either of the following:
val q1 = for{
t < table1 if t.rev === (
table2.filter(_.id === t.id).map(_.rev).max
)
} yield t
val q2 = table1.filter{t=> t.rev === (
table2.filter(_.id === t.id).map(_.rev).max
)}.map(identity)
EDIT based on comment:
val q = (for{
t1 < table1; t2 <- table2 if t1.id === t2.id
} yield t1).orderBy(_.version.max).reverse.take(1)
Related
I wrote raw query to psql and it's work fine but when i wrote this in sqlalchemy my WHERE clause duplicated to FROM clause.
select id from T1 where arr && array(select l.id from T1 as l where l.box && box '((0,0),(50,50))');
In this query i fetch all id from T1 where array with ints intersects with results from subquery.
class T1():
arr = Column(ARRAY(Integer))
...
class T2():
box = Column(Box) # my geometry type
...
1 verison:
layers_q = select([T2.id]).where(T2.box.op('&&')(box)) # try find all T2 intersects with box
chunks = select([T1.id]).where(T1.arr.overlap(layers_q)) # try find all T1.id where T1.arr overlap with result from first query
SELECT T1.id
FROM T1
WHERE T1.arr && (SELECT T2.id
FROM T2
WHERE T2.box && %(box_1)s)
This i have a PG error about type cast. I understand it.
2 version:
layers_q = select([T2.id]).where(T2.box.op('&&')(box))
chunks = select([T1.id]).where(T1.arr.overlap(func.array(layers_q)))
I added func.array() for cast to array but result is not correct:
SELECT T1.id
FROM T1, (SELECT T2.id AS id
FROM T2
WHERE T2.box && %(box_1)s)
WHERE T1.arr && array((SELECT T2.id
FROM T2
WHERE T2.box && %(box_1)s))
There you can see what i have duplicate in FROM clause. How did it correctly?
I find solution!
func.array(select([T2.id]).where(T2.box.op('&&')(box)).as_scalar())
After added as_scalar() all be good, beacause in my select all ids need have in one array.
I can easily select rows which I should update.
select
p.id,
(regexp_match( p.name, '\d+'))[1] as renum,
pd.quantity
from package p
left join package_detail pd on
pd.package_id = p.id and resource_type_id is null
where p.name like '%Bit%';
But how to write query to update quantity by renum from the result above?
I am not looking for the query. I am looking the rule to complete this task.
You can find background in the docs (https://www.postgresql.org/docs/current/sql-update.html ) but if you've got a query that gives the result you want, you can use that query as a correlated subquery in the update command:
UPDATE table1 t1 SET (col1, col2, col3) = (select t2.val1, t2.val2, t2.val3 from table2 t2 where t2.table1_id = t1.id)
WHERE t1.col1 IS NULL
In your case, this might take the form or something similar to:
UPDATE package p2 SET (quantity) = (
select ((regexp_match( p.name, '\d+'))[1])::integer + pd.quantity
from package p
left join package_detail pd on pd.package_id = p.id and resource_type_id is null
where p.name like '%Bit%'
and p2.id = p.id
and ((regexp_match( p.name, '\d+'))[1])::integer + pd.quantity IS NOT NULL )
WHERE p2.name like '%Bit%'
I am trying to join a table on a subquery, but I don't know how to express it using Sequelize ORM. This is the raw SQL I want to run:
SELECT *
FROM table_a a
LEFT OUTER JOIN (SELECT * FROM table_b b WHERE col = VAL) ON a.id = b.id;
I tried
A.findAll({
include: [
{
model: B,
where: { col: val },
}
]
}).then(...);
but that doesn't get me the query I want. Instead it changes the join to an INNER JOIN, and joins on col = VALUE instead. Is there a way to do a join on the result of a subquery? I am using Postgres if it matters.
Update: After making the following change, the resulting query now uses a LEFT OUTER JOIN as expected:
include: [
{
model: B,
where: { col: val },
required: false,
}
]
However, it is still joining on col = VALUE, the generated query looks like:
SELECT * FROM table_a a
LEFT OUTER JOIN table_b b ON a.id = b.id AND b.col = VALUE;
These 2 queries ARE functionally equivalent:
SELECT * FROM table_a a
LEFT OUTER JOIN (SELECT * FROM table_b b WHERE col = VAL) ON a.id = b.id;
SELECT * FROM table_a a
LEFT OUTER JOIN table_b b ON a.id = b.id AND b.col = VALUE;
There is NO ADVANTAGE from the first one whatsoever. So, if the first one provides the wanted results, so should the second one.
Is it possible to convert below LINQ query from Comprehension to "Lambda" syntax, that is table1.where().select().
from t1 in table1
from t2 in table2.Where(t2=>t2.Table1ID == t1.ID).DefaultIfEmpty()
select new {t1.C1, t2.C2}
Above query will be translated to a left join in SQL without using the ugly Join keyword in LINQ.
LinqPad gives this translation:
Table1
.SelectMany (
t1 =>
Table2
.Where (t2 => (t2.Table1ID) == t1.ID)
.DefaultIfEmpty (),
(t1, t2) =>
new
{
C1 = t1.C1,
C2 = t2.C2
}
)
Can any one convert following SQL statement to Entity Framework C# or VB.net for me?
SQL statement:
select t1.*, t2.*
from tblWISTransacs t1
inner join tblWCBTransacs t2 on t1.TicketNo = t2.TicketNo
or t1.TicketNo = t2.customernumber
var result = (from t1 in dbContext.tblWISTransacs
join t2 in dbContext.tblWCBTransacs on 1 equals 1
where (t1.TicketNo == t2.TicketNo || t1.TicketNo == t2.customernumber)
select new { t1, t2 }).ToList();
The generated SQL is a bit different from Palani Kumar's, but you could also use
from t1 in db.tblWISTransacs
from t2 in db.tblWCBTransacs
where t1.TicketNo == t2.TicketNo || t1.TicketNo == t2.customernumber
select new { T1 = t1, T2 = t2 }
I think both end up essentially as a cross join.