How to get entities in a many-to-many relationship that do NOT have a corresponding linked entity with DQL and Doctrine? - doctrine

I have a standard many-to-many relationship set up. Entity A can have many of Entity B, and vice versa.
I'm trying to get a list of all Entity A that do NOT have any corresponding Entity B. In SQL, I'd run a query like this:
SELECT a.* FROM entity_a a LEFT JOIN a_b r ON r.AID = a.id WHERE r.BID IS NULL
In this query, a_b is the linking table.
I'm trying to write a DQL statement (or use some other method) to get the same result, but the following does not work:
SELECT s FROM VendorMyBundle:EntityA s LEFT JOIN VendorMyOtherBundle:EntityB u WHERE u IS NULL
How can I achieve what I'm trying to do?

First, I have to underline that usually you should JOIN on the property of the entity (i.e. s), e.g. instead of:
SELECT s FROM VendorMyBundle:EntityA s
LEFT JOIN VendorMyOtherBundle:EntityB u WHERE u IS NULL
you should have something like:
SELECT s FROM VendorMyBundle:EntityA s
LEFT JOIN s.mylistofb u WHERE u IS NULL
where I'm supposing that in entity A you have defined your relationship as:
class A{
// ...
/**
* #ManyToMany(targetEntity="Vendor\MyBundle\Entity\EntityB")
* #JoinTable(name="as_bs",
* joinColumns={#JoinColumn(name="a_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="b_id", referencedColumnName="id", unique=true)}
* )
**/
private $mylistofb;
This stated, if the query is not working yet, then try the following:
SELECT s FROM VendorMyBundle:EntityA s
WHERE SIZE(s.mylistofb) < 1
It is simplest than the previous and also comes from the official docs (i.e. see "phonenumbers example").

Related

Using query hints to use a index in an inner table

I have a query which uses the view a as follows and the query is extremely slow.
select *
from a
where a.id = 1 and a.name = 'Ann';
The view a is made up another four views b,c,d,e.
select b.id, c.name, c.age, e.town
from b,c,d,e
where c.name = b.name AND c.id = d.id AND d.name = e.name;
I have created an index on the table of c named c_test and I need to use it when executing the first query.
Is this possible?
Are you really using this deprecated 1980s join syntax? You shouldn't. Use proper explicit joins (INNER JOIN in your case).
You are joining the two tables C and D on their IDs. That should mean they are 1:1 related. If not, "ID" is a misnomer, because an ID is supposed to identify a row.
Now let's look at the access route: You have the ID from table B and the name from tables B and C. We can tell from the column name that b.id is unique and Oracle guarantees this with a unique index, if the database is set up properly.
This means the DBMS will look for the B row with ID 1, find it instantly in the index, find the row instantly in the table, see the name and see whether it matches 'Ann'.
The only thing that can be slow hence is joining C, D, and E. Joining on unique IDs is extremely fast. Joining on (non-unigue?) names is only fast, if you provide indexes on the names. I'd recommend the following indexes accordingly:
create index idx_c on c (name);
create index idx_e on e (name);
To get this faster still, use covering indexes instead:
create index idx_b on b (id, name);
create index idx_c on c (name, id, age);
create index idx_d on d (id, name);
create index idx_e on e (name, town);

Hibernate, Order by count of subquery on ManyToMany using Predicates

I have a query written using Predicates in Hibernate and I need to add a subquery on a join table to count the number of joins and order by the number of joins where they exist in an array of ids.
The join table is a ManyToMany relation.
I am using flyway to setup the table schema, so while the join table exists in the database, a join model is not needed in Hibernate to join the 2 related models therefore no join model exists.
I don't care about retrieving these related models, I just want the number of joins so that I can order by them.
The following is PostGreSQL, which works. I need to convert the following PSQL into a Predicate based query:
SELECT u.*, COUNT(jui.interest_id) AS juiCount
FROM "user" u
LEFT JOIN (
SELECT ui.user_id, ui.interest_id
FROM user_interest ui
WHERE ui.interest_id IN (?)
) AS jui ON u.id = jui.user_id
GROUP BY u.id
ORDER BY juiCount DESC
Where the ids provided for the IN condition are passed into the subquery. The above query is in PostGreSQL.
Working with what I have so far:
CriteriaBuilder b = em.getCriteriaBuilder();
CriteriaQuery<User> q = b.createQuery(User.class);
Root<User> u = q.from(User.class);
// This doesn't make sense because this is not a join table
// Subquery<Interest> sq = q.subquery(Interest.class)
// Root<Interest> squi = sq.from(Interest.class);
// sq.select(squi);
// sq.where(b.in("interest_id", new LiteralExpression<Long[]>((CriteriaBuilderImpl) b, interestIds)));
q.orderBy(
// b.desc(b.tuple(u, b.count(squi))),
b.asc(u.get(User_.id))
);
q.where(p);
return em
.createQuery(q)
.getResultList();
Everything I have managed to find doesn't quite seem to fit right given that they are not using ManyToMany in the use of q.subquery() in their example.
Anyone can help fill in the blanks on this please?

Codeigniter : Want to Implement Left join by useing Doctrine 2 library

Please help me want to left join two table in Codeigniter with Orm docrtrine 2 libray.
Doctrine entity model doesn't give association for one to many and vice-versa. To allow these feature you have to update your entities with valid association. Below is an example for such two tables which contains user information in users table and there favorite meals in UserFavoriteMeals
For Left JOIN update needed in both entities for association explained below :
In user entity add onetomany association of UserFavoriteMeals where mappedby is the key on basis of which association happens in db.
/**
* #var \Entity\UserFavoriteMeals
*
* #OneToMany(targetEntity="Entity\UserFavoriteMeals", mappedBy="userid" )
* #JoinColumns({
* #JoinColumn(name="id", referencedColumnName="userId", nullable=true)
* })
*/
private $UserFavoriteMeals;
Simillary, Put manyToOne association in UserFavoriteMeals entity
/**
* #var \Entity\Users
*
* #ManyToOne(targetEntity="Entity\Users")
* #JoinColumns({
* #JoinColumn(name="userId", referencedColumnName="id", nullable=true)
* })
*/
private $userid;
In these manner we have to manage associations for Left JOIN, now simply write a Left JOIN query in below format :
$left_query = $this->em->createQuery("SELECT fm,u FROM Entity\userFavoriteMeals fm LEFT JOIN fm.userid u WHERE fm.userId = 231 ")->getArrayResult();
print_r($left_query);
$left_query_inverse = $this->em->createQuery("SELECT u,fm FROM Entity\Users u LEFT JOIN u.UserFavoriteMeals fm WHERE u.id = 4")->getArrayResult();
print_r($left_query_inverse);
First you need to integrate Doctrine into CodeIgnitor.
http://docs.doctrine-project.org/en/2.0.x/cookbook/integrating-with-codeigniter.html
This is how you use custom query to left join two tables in Doctrine.
<?php
$query = $em->createQuery('SELECT u.id, a.id as article_id FROM CmsUser u LEFT JOIN u.articles a');
$results = $query->getResult(); // array of user ids and every article_id for each user
More on custom query :- http://docs.doctrine-project.org/en/2.1/reference/dql-doctrine-query-language.html
If you want DQL way, which is preferred, it should be something like this.
$qb->select('u')
->from('Entity_User', 'u')
->leftJoin('u.profile','p')
->leftJoin('a.user_details','ud')
->where('u.id = :id')
->setParameter('id','100')
->getQuery();
More on DQL :- http://docs.doctrine-project.org/en/2.0.x/reference/query-builder.html
I hope this helps,
Cheers!

Select value from grandchildren

I have the following table structure:
I want to select:
all TableA entries + the Identifier column from Table C that have:
a special value in TableBType ("TableBTypeValue")
a special value in TableCType ("TableCTypeValue")
The problem that I have is that the linq queries seem to fail when there are TableA entries that have no TableB entry or if there are TableB entries without a TableC (TableBType and TableCType is mandatory so they don't have that problem).
With SQL this would not be a big problem, but as I am new to linq I could not find the correct way to create this query.
I think this is what you are looking for:
from c in db.TableC
where c.TableCType == TableCTypeValue
join b in db.TableB on c.TableBId equals b.Id
where b.TableBType == TableBTypeValue
join a in db.TableA on b.TableAId equals a.Id
select new { a, c.Identifier };
Hope it helps.

Linq To Entity Framework selecting whole tables

I have the following Linq statement:
(from order in Orders.AsEnumerable()
join component in Components.AsEnumerable()
on order.ORDER_ID equals component.ORDER_ID
join detail in Detailss.AsEnumerable()
on component.RESULT_ID equals detail.RESULT_ID
where orderRestrict.ORDER_MNEMONIC == "MyOrderText"
select new
{
Mnemonic = detail.TEST_MNEMONIC,
OrderID = component.ORDER_ID,
SeqNumber = component.SEQ_NUM
}).ToList()
I expect this to put out the following query:
select *
from Orders ord (NoLock)
join Component comp (NoLock)
on ord .ORDER_ID = comp.ORDER_ID
join Details detail (NoLock)
on comp.RESULT_TEST_NUM = detail .RESULT_TEST_NUM
where res.ORDER_MNEMONIC = 'MyOrderText'
but instead I get 3 seperate queries that select all rows from the tables. I am guessing that Linq is then filtering the values because I do get the correct values in the end.
The problem is that it takes WAY WAY too long because it is pulling down all the rows from all three tables.
Any ideas how I can fix that?
Remove the .AsEnumerable()s from the query as these are preventing the entire query being evaluated on the server.

Resources