I would like to use a select to get an array of entities with Doctrines QueryBuilder. But I need an ORDER BY which uses a foreign attribute (attribute in a table related with a foreign key). What I would like to write intuitively is something like this:
$repo = $this->getDoctrine()->getRepository('MyBundle:relation_table');
$query = $repo->createQueryBuilder('r')
->orderBy('r.fevent.date', 'DESC')
->getQuery();
Which, not surprisingly, doesn't work. In SQL my SELECT looks like this:
SELECT r.* FROM relation_table AS r
INNER JOIN events AS e
ON e.IDevent = r.Fevent
ORDER BY e.date
But I also need Doctrine to give me the entity-object back. I think of two possible solutions:
Use the QueryBuilder to create an INNER JOIN, or
Create a free SQL Statement, same as above, and tell Doctrine somehow to create an entity object with its results.
Any hints? Thanks.
You need to join the entity you want to order with:
$query = $repo->createQueryBuilder('r')
->join('r.fevent', 'f')
->orderBy('f.date', 'DESC')
->getQuery()
;
Joining both tables in your Doctrine Query (the first of your proposed solutions) is pretty straigtforward. Take a look here: http://symfony.com/doc/2.0/book/doctrine.html#joining-to-related-records
A similar question was answered here: Doctrine 2: How to search for an entity by its association's value?
Related
I have been observed ActiveRecord delete_all is ignoring the joins table condition. Is this known issue from rails community?
Query:
DesignPartCategory.joins(:category).where(category: {site_id: INDIA}, designpart_uuid: ['123C']).delete_all
Expected result:
DELETE FROM designpart_category WHERE designpart_category.designpart_uuid IN ('123C') AND designpart_category.category_id IN (INDIA);
Actual Result:
DELETE FROM `designpart_category` WHERE `designpart_category`.`designpart_uuid` IN (SELECT designpart_uuid FROM (SELECT `designpart_category`.`designpart_uuid` FROM `designpart_category` INNER JOIN `category` ON `category`.`category_id` = `designpart_category`.`category_id` WHERE (category.site_id =INDIA AND designpart_category.designpart_uuid in ('123C'))) __active_record_temp);
Currently delete_all operation just ignoring/discards the joins table condition and executing the rest of the query.
I'm assuming it should not be the case, it should throw the exception instead of ignoring joins. Please let us know your thoughts/comments on it.
Seems there is some typo in your syntax, checkout this -
DesignPartCategory.joins(:category).where("categories.site_id = ? AND categories.designpart_uuid IN (?)", 'INDIA', ['123C']).delete_all
Alternatively you can try this: -
DesignPartCategory.joins(:category).where(categories: {site_id: 'INDIA', designpart_uuid: (['123C'])}).delete_all
Note: - Delete vs Destroy
Have you checked following in your query?
DELETE FROM `designpart_category`
WHERE `designpart_category`.`designpart_uuid` IN (
SELECT designpart_uuid FROM (
SELECT `designpart_category`.`designpart_uuid`
FROM `designpart_category` INNER JOIN `category`
ON `category`.`category_id` = `designpart_category`.`category_id`
WHERE (category.site_id =INDIA AND designpart_category.designpart_uuid in ('123C')
)
) __active_record_temp
);
It filters as per your join query, check query fired in IN
delete_all Deletes the records matching conditions without instantiating the records first, and hence not calling the destroy method nor invoking callbacks. So it will not take anything into account like join, includes etc...
Check the documentation
I have some query and I need in select block select id relation entity, how can I do it without some join, like in SQL? In example I add leftJoin but I want understand it's possible without join like lsc.serviceCompany.id or how ?
$qb
->select('
ser_com.id as serviceCompanyId
')
->from('AppBundle:LocationServiceCompany', 'lsc')
->leftJoin('lsc.serviceCompany', 'ser_com')
->where('lsc.serviceCompany = :sc')
->setParameter('sc', $serviceCompany);
$qb->select(IDENTITY(lsc.serviceCompany)) (...)
Duplicate of this question
It's been a while since I've written raw SQL, I was hoping someone could help me out in optimizing this SQL query so that it works across, both, MySQL and PostgreSQL.
I would also have to implement this via CodeIgniter (2.x) using ActiveRecord, any help/advice?
SELECT *
FROM notaries, contact_notaries
WHERE notaries.id = contact_notaries.notary_id
AND WHERE ( contact_notaries.city LIKE %$criteria%
OR contact_notaries.state LIKE %$criteria
OR contact_notaries.address LIKE %$criteria%)
Thanks!
Each query can have just one WHERE clause (you don't need the second)
It's much better to put join condition into JOIN rather then WHERE.
Are you sure you really need all the columns from 2 tables (*)?
So I'd refactor it to
SELECT [field_list]
FROM notaries
INNER JOIN contact_notaries ON (notaries.id = contact_notaries.notary_id)
WHERE ( contact_notaries.city LIKE '%$criteria%'
OR contact_notaries.state LIKE '%$criteria'
OR contact_notaries.address LIKE '%$criteria%')
Using a1ex07's query:
SELECT [field_list]
FROM notaries
INNER JOIN contact_notaries ON (notaries.id = contact_notaries.notary_id)
WHERE ( contact_notaries.city LIKE '%$criteria%'
OR contact_notaries.state LIKE '%$criteria'
OR contact_notaries.address LIKE '%$criteria%')
Active record:
$this->db->select(); // Leave empty to select all fields
$this->db->join('contact_notaries', 'notaries.id = contact_notaries.notary_id', 'inner');
$this->db->like('contact_notaries.city', 'criteria');
$this->db->like('contact_notaries.state', 'criteria');
$this->db->like('contact_notaries.address', 'match');
$results = $this->db->get('notaries');
To specify a list of fields you can do $this->db->select('field_1, field_2, ...');.
http://codeigniter.com/user_guide/database/active_record.html
This question follows on from the questions here and here.
I have recently upgraded to Propel 1.5, and have started using it's Query features over Criteria. I have a query I cannot translate, however - a left join with multiple criteria:
SELECT * FROM person
LEFT JOIN group_membership ON
person.id = group_membership.person_id
AND group_id = 1
WHERE group_membership.person_id is null;
Its aim is to find all people not in the specified group. Previously I was using the following code to accomplish this:
$criteria->addJoin(array(
self::ID,
GroupMembershipPeer::GROUP_ID,
), array(
GroupMembershipPeer::PERSON_ID,
$group_id,
),
Criteria::LEFT_JOIN);
$criteria->add(GroupMembershipPeer::PERSON_ID, null, Criteria::EQUAL);
I considered performing a query for all people in that group, getting the primary keys and adding a NOT IN on the array, but there didn't seem a particularly easy way to get the primary keys from a find, and it didn't seem very elegant.
An article on codenugget.org details how to add extra criteria to a join, which I attempted:
$result = $this->leftJoin('GroupMembership');
$result->getJoin('GroupMembership')
->addCondition(GroupMembershipPeer::GROUP_ID, $group->getId());
return $result
->useGroupMembershipQuery()
->filterByPersonId(null)
->endUse();
Unfortunately, the 'useGroupMembershipQuery' overrides the left join. To solve this, I tried the following code:
$result = $this
->useGroupMembershipQuery('GroupMembership', Criteria::LEFT_JOIN)
->filterByPersonId(null)
->endUse();
$result->getJoin('GroupMembership')
->addCondition(GroupMembershipPeer::GROUP_ID, $group->getId());
return $tmp;
For some reason this results in a cross join being performed for some reason:
SELECT * FROM `person`
CROSS JOIN `group_membership`
LEFT JOIN group_membership GroupMembership ON
(person.ID=GroupMembership.PERSON_ID
AND group_membership.GROUP_ID=3)
WHERE group_membership.PERSON_ID IS NULL
Does anyone know why this might be doing this, or how one might perform this join successfully in Propel 1.5, without having to resort to Criteria, again?
Propel 1.6 supports multiple criteria on joins with addJoinCondition(). If you update the Symfony plugin, or move to sfPropelORMPlugin, you can take advantage of that. The query can then be written like this:
return $this
->leftJoin('GroupMembership')
->addJoinCondition('GroupMembership', 'GroupMembership.GroupId = ?', $group->getId())
->where('GroupMembership.PersonId IS NULL');
Consider following two tables:
tag_names (tag_id, tag_name)
tag_links (tag_id, image_id)
An image can have multiple tags, I want to select all tags for a specific image id.
I am trying following query, but it doesnt seem to select correctly (selects only one row), What is wrong with it?
SELECT tag_name
FROM tag_names
LEFT JOIN tag_links.tag_id = tag_names.tag_id
WHERE tag_links.image_id = $image_id
Edit: I'm using CodeIgniter Active record query, but I wrote in basic SQL format so that if someone is not fimiliar with CodeIgniter can help. However, this query works fine with simple mysql format (without using CodeIgniter) but strangely does not work with CodeIgniter, even there is no any problem with the syntax, it just selects one row.
Here is CodeIgniter Syntax:
$this->db->select('tag_name');
$this->db->from('tag_names');
$this->db->join('tag_links', 'tag_links.tag_id = tag_names.tag_id', 'left');
$this -> db -> where('tag_links.image_id', (int)$image_id);
$query = $this->db->get();
Try this:
SELECT tag_name
FROM tag_names
LEFT JOIN tag_links
ON tag_links.tag_id = tag_names.tag_id
WHERE tag_links.image_id = $image_id
IMHO you forgot to join table (properly with ON statement) you are using.
EDIT: I have 2 ideas how to get rid of the problem:
First:
Change the line with SELECT
$this->db->select('tag_names.tag_name');
Second:
Use select() function with complete query:
$this->db->select($query, false);
$this->db->select() accepts an optional second parameter. If you set
it to FALSE, CodeIgniter will not try to protect your field or table
names with backticks. This is useful if you need a compound select
statement.
from: http://codeigniter.com/user_guide/database/active_record.html#select
It seems that you have a syntax error (you forgot tag_links in JOIN clause). By the way in my opinion you don't need LEFT JOIN for this purpose otherwise you may get incorrect results.
SELECT tag_name
FROM
tag_names
JOIN tag_links ON tag_links.tag_id = tag_names.tag_id
WHERE tag_links.image_id = $image_id
SELECT tag_names.tag_name
FROM tag_links
LEFT JOIN tag_names.tag_id = tag_links.tag_id
WHERE tag_links.image_id = $image_id
tag_names is only going to have single entry for a given ID, which means your query will return a single result. You need to primarily select from tag_links and then join the name of the tag on top of it, so you correctly select from the table with the multiple entries.