Using HQL exclude parents that have a child with a specific value - hql

I have some tables with a relationship like
Parent
------
parentPk
//data
Child
------
parentFk
status
//data
I want to retrieve all the parents without a child in a specific status. Now, I could do this with a "not in" clause like
... where parentPk not in (select parentFk from Child where status="ABC")
However, this seems inefficient. What I'd really like to do is something like
where "ABC" not in elements(Parent.child.status)
but obviously that doesn't work because status is not a collection. Is there a way to make it do what I want or is the "not in" clause my best bet?

I solved this by using
where "ABC" not in (select child.status from Child as child where child.parentFk = parent.parentPk)
Still not ideal, but better than retrieving all keys

Related

Hierarchical query to find root and return singular path

I am working with a black box database which I did not create, nor can I edit. Also, this select query needs to run in jasper reports so I cannot write a stored procedure.
I have an inventory system which uses a parent/child mapping table and produced new keys each time there is a change in inventory status. I am working with 2 tables these are the important fields and a simplified query:
allinv which contains fields:
invmaster
invkey
and
pclink which contains fields (corresponds to invkeys for allinv above):
parent
child
The following query works for one inventory item and shows the progression as expected but it requires knowing the root and providing the master key.
My question then is, if I need to return all inventory items (remove the where clause) with this structure is there a way to automatically detect the root element and set that is the 'start with' or something that would work similarly so I can use this as a subquery to an analytical window query to pull root, leaf(s) and statuses along the way?
select
ai.invkey AS sxkey,
stl.parent as parent,
stl.child as child,
level as lvl,
CONNECT_BY_ISLEAF as IsLeaf,
CONNECT_BY_ROOT(STL.parent) as root
from eprog.allinv ai
left join eprog.pclink stl
on ai.invkey = stl.parent
where invmasterkey = 'SA3010401'
start with stl.parent = '#gRR5'
connect by nocycle prior stl.child = stl.parent;
I'm not sure I entirely understand your question, but you can certainly do:
START WITH stl.parent IS NULL
to start your hierarchical query with those rows.

Error : FRM-41337:Cannot populate the list from record group

I have a record group that is using a block item, i.e. where cust_id = :order.cust_id
Sometimes it works, sometimes not.
When I query an existing record, I am able to add a new line and enter the condition code i.e. from the populated record group. But when I enter a new order, the list is empty. I tried to put the code in when-new-record-instance, but I get an error
select profile profile1, profile profile2
from dss.v_unit_conditions
where cust_id = :order.dsp_cust_id
and profile_type = 'UC'
and active = 'Y'
41337 - cannot populate list from record group
If I use that in when-tab-change, then I get the same error.
When you perform query, you acquire :ORDER.DSP_CUST_ID value so Record Group Query fetches something.
On the other hand, when you're entering a new order, I presume that :ORDER.DSP_CUST_ID is empty, query doesn't return anything and raises an error.
It means that :ORDER.DSP_CUST_ID must be known. In order to make the Record Group Query work, consider creating it dynamically, i.e. when :ORDER.DSP_CUST_ID gets its value. As it seems that you're entering it manually, the WHEN-VALIDATE-ITEM might be your choice. Have a look at CREATE_GROUP_FROM_QUERY (and, possibly, POPULATE_GROUP_FROM_QUERY) built-ins. They are described (with examples) in Forms Online Help System.

Linq return list of categories in order

I tried to search for this on Google/SO but I didn't really know what to search for!
Given:
tblCategories
-----------------
ID
Name
ParentID
And given say a category ID n how would we return it's parent category, and the parent of it's parent etc, until ParentID = 0?
There are plenty of other questions on this type of issue - try searching for "recursive linq query" - https://stackoverflow.com/search?q=recursive+linq+query
The general answers are:
either fetch everything into memory and use something like AsHierarchy in Linq-to-Objects - see http://www.scip.be/index.php?Page=ArticlesNET18#AsHierarchy
or write a CommonTableExpression in a stored procedure to help - http://msdn.microsoft.com/en-us/library/ms186243.aspx

How do I sort, group a query properly that returns a tuple of an orm object and a custom column?

I am looking for a way to have a query that returns a tuple first sorted by a column, then grouped by another (in that order). Simply .sort_by().group_by() didn't appear to work. Now I tried the following, which made the return value go wrong (I just got the orm object, not the initial tuple), but read for yourself in detail:
Base scenario:
There is a query which queries for test orm objects linked from the test3 table through foreign keys.
This query also returns a column named linked that either contains true or false. It is originally ungrouped.
my_query = session.query(test_orm_object)
... lots of stuff like joining various things ...
add_column(..condition that either puts 'true' or 'false' into the column..)
So the original return value is a tuple (the orm object, and additionally the true/false column).
Now this query should be grouped for the test orm objects (so the test.id column), but before that, sorted by the linked column so entries with true are preferred during the grouping.
Assuming the current unsorted, ungrouped query is stored in my_query, my approach to achieve this was this:
# Get a sorted subquery
tmpquery = my_query.order_by(desc('linked')).subquery()
# Read the column out of the sub query
my_query = session.query(tmpquery).add_columns(getattr(tmpquery.c,'linked').label('linked'))
my_query = my_query.group_by(getattr(tmpquery.c, 'id')) # Group objects
The resulting SQL query when running this is (it looks fine to me btw - the subquery 'anon_1' is inside itself properly sorted, then fetched and its id aswell as the 'linked' column is extracted (amongst a few other columns SQLAlchemy wants to have apparently), and the result is properly grouped):
SELECT anon_1.id AS anon_1_id, anon_1.name AS anon_1_name, anon_1.fk_test3 AS anon_1_fk_test3, anon_1.linked AS anon_1_linked, anon_1.linked AS linked
FROM (
SELECT test.id AS id, test.name AS name, test.fk_test3 AS fk_test3, CASE WHEN (anon_2.id = 87799534) THEN 'true' ELSE 'false' END AS linked
FROM test LEFT OUTER JOIN (SELECT test3.id AS id, test3.fk_testvalue AS fk_testvalue
FROM test3)
AS anon_2 ON anon_2.fk_testvalue = test.id ORDER BY linked DESC
)
AS anon_1 GROUP BY anon_1.id
I tested it in phpmyadmin, where it gave me, as expected, the id column (for the orm object id), then the additional columns SQL_Alchemy seems to want there, and the linked column. So far, so good.
Now my expected return values would be, as they were from the original unsorted, ungrouped query:
A tuple: 'test' orm object (anon_1.id column), 'true'/'false' value (linked column)
The actual return value of the new sorted/grouped query is however (the original query DOES indeed return a touple before the code above is applied):
'test' orm object only
Why is that so and how can I fix it?
Excuse me if that approach turns out to be somewhat flawed.
What I actually want is, have the original query simply sorted, then grouped without touching the return values. As you can see above, my attempt was to 'restore' the additional return value again, but that didn't work. What should I do instead, if this approach is fundamentally wrong?
Explanation for the subquery use:
The point of the whole subquery is to force SQLAlchemy to execute this query separately as a first step.
I want to order the results first, and then group the ordered results. That seems to be hard to do properly in one step (when trying manually with SQL I had issues combining order and group by in one step as I wanted).
Therefore I don't simply order, group, but I order first, then subquery it to enforce that the order step is actually completed first, and then I group it.
Judging from manual PHPMyAdmin tests with the generated SQL, this seems to work fine. The actual problem is that the original query (which is now wrapped as the subquery you were confused about) had an added column, and now by wrapping it up as a subquery, that column is gone from the overall result. And my attempt to readd it to the outer wrapping failed.
It would be much better if you provided examples. I don't know if these columns are in separate tables or what not. Just looking at your first paragraph, I would do something like this:
a = session.query(Table1, Table2.column).\
join(Table2, Table1.foreign_key == Table2.id).\
filter(...).group_by(Table2.id).order_by(Table1.property.desc()).all()
I don't know exactly what you're trying to do since I need to look at your actual model, but it should look something like this with maybe the tables/objs flipped around or more filters.

Linq-to-sql Not Contains or Not in?

I'm building a poll widget. I've 2 tables, call them Polls and PollsCompleted. I need to do a linq query to get all the Polls that do not exist for a given user in PollsCompleted.
I have the following sets:
For Polls
Where Active == True
For PollsCompleted
Where UserId == ThisUserId
Where PollId = Polls.Id
Now I need to get all Polls that do not exist in PollsCompleted. I need an example for this using either a single or multiple queries. I've tried to break it down into 2 queries.
Basically, I've 2 IQueryables of type T and T1. I want to take all T's where T.ID does not exist in T1.ParentId.
T.Where(x => ! T1.Select(y => y.ParentID).Contains(x.ID))
In Linq you often work from the bottom up. Here we first get a collection of all the parentIDs in T1 -- the T1.Select(...) part. Then we create a where clause that selects all of the Ts whose IDs are not contained in that set.
Note that the result is a query. To materialize it, use ToList() or similar on the statement above.
Use Except. That will work in this case.
For your reference Enumerable.Except Method

Resources