Is JPA subquery in FROM clause possible? - jpa

I'm having a little problem with JPA. Consider this scenario:
Table A (id_a) | Table B (id_b, id_a)
What I need is a query like this:
Select a.*, c.quantity from A as a, (Select Count(*) as quantity
from B as b where b.id_a = a.id_a) as c;
The thing is that I want to use a jpa query and not a native query, something like this:
Select a, c FROM A a, (Select Count(b) FROM B b where a.idA = b.a.idA) c;
So then I could iterate from the result (a list of Object[] with a and c in each node) and then assign a.quantity = c;
I repeat, I don't want to use native query, but I found no other way than use redundant data, and add another column to A called Quantity and every time I insert and delete from B, update this column in A.
Please help, I read somewhere that JPA doesn't accept subqueries in Form clause, so, what can I do ?
Thanks a lot !

JPA does not support sub-selects in the FROM clause but EclipseLink 2.4 current milestones builds does have this support.
See,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#Sub-selects_in_FROM_clause
You can probably rewrite the query with just normal joins though.
Maybe,
Select a, size(a.bs) from A a
or
Select a, count(b) from A a join a.bs b group by a

Related

RECORD to JSONB, no automatic way?

jsonb_build_object('a',a, 'b',b) is redundant (not "automatic"), and to_jsonb(row(a,b)) is ugly because ignores column names... Is there no way to do the right thing?
NOTES
A typical query is something as
SELECT a,b, record_to_jsonb(c,d,e) as info FROM t
I need a dynamic solution, but, to illustrate, a statical solution is to define a datatype,
CREATE TYPE mytest AS (c text, d int, e boolean);
SELECT a,b, to_jsonb(row(c,d,e)::mytest) as info FROM t; -- work fine!
PS: why PostgreSQL not offers the inverse of jsonb_to_record()? Either I'm not realizing to the see an elegant and eficient way to use to_jsonb (most probable), or, maybe PostgreSQL's architect-developers forgot the concept of library function orthogonality... There is no technical problem to implement a nice record_to_jsonb() function, as demonstrated before by functions like xmlattributes(a,b), that captures colunm name and value.
select a, b, to_jsonb(subq) as info
from t
cross join lateral (values (c, d, e)) as subq(c, d, e);
or shorter, abbreviating CROSS JOIN syntax and using SELECT clause directly
select a, b, to_jsonb(subq) as info
from t, lateral (select c, d, e) subq;
Could something like this be more in line with your use case? My thought would be to keep a and b in the json and let the requesting code just ignore it.
select a, b, to_jsonb(t) - 'a' - 'b' as info
from t

Why doesn't postgres throw error when no join predicate is given in the FROM clause of an UPDATE

For example in the following query:
UPDATE A
SET A.a = b.id
FROM (SELECT * FROM B) b;
This query doesn't throw any error.
What does the FROM do in this case.
Does it do a cross product between A and B, Then pick some random entry from B?
When i do explain i don't see any join, When i add a join predicate in where then there's a hash join. But not in this case.
Just curious about the functioning, Don't plan on using this query.
Your query is in fact an update join, according to Postgres syntax, but it is lacking a WHERE clause which would provide the join condition between the two tables. Most likely, you intended to use something along these lines:
UPDATE A a
SET A.a = b.id
FROM B b
WHERE a.pk = b.fk; -- join condition is here
As it stands now, every record in the A table would be joined to every record in the B table, so the update logic is not well defined.
Your table and subquery doesn't have any reference row which to update. So this will pickup the first row in B.
UPDATE A
SET A.a = b.id
FROM (SELECT * FROM B) b;
For your question, why this is working, is it because b = SELECT * FROM B, subqueries can function as result table.

Is it possible to create a view for a subquery referring the main query?

If have a query that uses a subquery. Basically it is like this:
SELECT A.name, A.pk
array_to_string(array(SELECT B.name FROM b WHERE B.relA = A.pk ),', ')
FROM A;
Basically it makes a column in A from a to-many relationship to B. (In my case A is a list of items and B contains tags related to that items. The query makes a column with a list of tags for each row in A.)
Since the real world query is more complex and I need the subquery more than one time, I want to make a view from the subquery (DRY). This is not possible, because A.pk is only known, if the subquery is a subquery in a main query that fetches from A. It is not known if the subquery stands alone. So I cannot create a view from the stand-alone version:
CREATE VIEW bview AS SELECT B.b FROM B WHERE B.relA=A.pk;
gives me the expected:
ERROR: missing FROM-clause entry for table "A"
Is there a way to define akin of "incomplete view", that is not executed itself, but in a main query completing the subquery without using functions?
Edit: The WHERE clause inside the subquery cannot be replaced with a JOIN clause, because it takes the A.pk from the outer query.
You can create a simple view without referring to table A and then use that as a row source in various parts of your complex query:
CREATE VIEW bview AS
SELECT relA, string_agg(name, ', ') AS tags
FROM b
GROUP BY relA;
This may seem inefficient because if you run the view like this without qualification, then all tags for all relA are concatenated. However, when you use the view in a larger query with qualifications, then the view is only evaluated for those relA values that are asked for in the outer query. This is because the view is "merged" with the outer query by the planner.
So you end up with:
SELECT name, pk, tags
FROM A
JOIN bview ON relA = pk;

How to take an intermediate data for the complex sql query. Postgresql

I have some complex queries to the postgresql which takes data from several tables joined each other with outer left join operators.
I need to test these queries so I need a fixtures for the tests contain only data I need, not whole tables data.
How could I see the intermediate results for these join subqueries to use it as a fixtures?
For example, I have tables A, B and C and query
SELECT A.column
FROM A
LEFT JOIN B ON A.b_id = B.id
LEFT JOIN C ON A.c_id = C.a_id
How could I take a result as "From table a: {part of A table taking part on query}, From table B {part of B table taking part on query}" etc, when parts of tables shows needed data or something like this. Is there any existing tool or method for it?
Unfortunately, EXPLAIN and ANALYSE shows only statistics and benchmarks, not data.
maybe you mean
SELECT A.*
FROM A
LEFT JOIN B ON A.b_id = B.id
LEFT JOIN C ON A.c_id = C.a_id
limit 10
to see what's happening in A from the join?
Or perhaps
select concat('from table a', a.col1, a.col2...) ,
concat('from table b', b.col1, b.col2...)
from ...
String functions such as concat: http://www.postgresql.org/docs/9.1/static/functions-string.html
also worth looking into http://www.postgresql.org/docs/9.1/static/functions-array.html at array_append()

Selecting all rows who belong to a group with some properties

I use PostgreSQL for a web application, and I've run into a type of query I can't think of a way to write efficiently.
What I'm trying to do is select all rows from a table which, when grouped a certain way, the group meets some criteria. For example, the naive way to structure this query might be something like this:
SELECT *
FROM table T
JOIN (
SELECT iT.a, iT.b, SUM(iT.c) AS sum
FROM table iT
GROUP BY iT.a, iT.b
) TG ON (TG.a = T.a AND TG.b = T.b)
WHERE TG.sum > 100;
The problem I'm having is that this effectively doubles the time it takes the query to execute, since it's essentially selecting the rows from that table twice.
How can I structure queries of this type efficiently?
You can try a window function although I don't know if it is more efficient. I guess it is as it avoids the join. Test this and your query with explain
select *
from (
select
a, b,
sum(c) over(partition by a, b) as sum
from t
) s
where "sum" > 100