create Query Builder symfony inner join - mysql

could anyone please convert this sql query into query builder in symfony.
Select a.* From article a
Inner Join
articles_devis ad On a.id=ad.article_id
Inner Join
devis d On d.id=ad.devis_id
Inner Join
utilisateurs u On u.id=d.user_id
Where u.id=7 and Where d.id=63
I have tried this line code but it didn't work
public function ArticlesByDevisByUser(){
$qb = $this->createQueryBuilder('a')
->select('a.*')
->from('ArticleBundle:Article', 'a')
->innerJoin('a.articledevis', 'ad')
->where('articles.id = ad.article')
->innerJoin('ad.devis', 'd')
->where('d.id = ad.devis')
->innerJoin('d.user', 'u')
->where('u.id = d.user')
->andWhere('u.user=7')
->andWhere('d.id=63');
return $qb->getQuery()->getResult();
}

You have to create a Repository and link it to your Article using #ORM\Entity annotation (in case it is not already done) :
In your Article entity :
/**
* #ORM\Entity(repositoryClass="YourProject\YourBundle\Entity\ArticleRepository")
*
*/
class Article
{
...
}
And then in your ArticleRepository put your function :
use Doctrine\ORM\EntityRepository;
class ArticleRepository extends EntityRepository
{
public function ArticlesByDevisByUser($userId, $devisId)
{
return $this->createQueryBuilder('a')
->innerJoin('a.articledevis', 'ad')
->innerJoin('a.devis', 'ad')
->innerJoin('a.user', 'au')
->where('ad.id = :devisId')
->andWhere('au.id = :userId')
->setParameter('userId', $userId)
->setParameter('devisId', $devisId)
->getQuery()
->getResult();
}
}
I put articledevis, devis and user for the innerJoin but it depends attributes names you give in your Article entity

Related

Spring Boot: How to create dynamic query involving 'join' and 'group by' using predicate

My post request body will be like
{
"queryCondition":[
{
"filter":"status",
"filterlist":["Closed","New","Resolved"...]
},
{
"filter":"assigned_team",
"filterlist":["A","B","C"...]
},
{
"filter":"assigned_to",
"filterlist":["ram","govind","ajith"...]
},
{
"filter":"duration",
"filterlist":["2020-02-01","2020-05-01"....]
}
....
....
],
"durationField":"created_date"
}
I receive the columns(filter) and values(filterlist) dynamically with which I need to build this query.
SELECT * FROM tickets
WHERE ticket_id IN (SELECT ticket_id FROM Tickets WHERE created_date >= '2020-02-01') AND created_date '2020-05-01'
AND status IN ('Closed','Resolved','New')
AND assigned_team IN ('A' , 'B', 'C')
AND assigned_to IN ('ram','govind','ajith');
I built this query dynamically using Predicate and it is working fine.
#Override
public List<Tickets> conditionedQuery(QueryCondition queryCondition) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tickets> query = cb.createQuery(Tickets.class);
Root<Tickets> ticket = query.from(Tickets.class);
List<Predicate> predicatessub = new ArrayList<>();
for(FilterConditions fc:queryCondition.getQueryCondition()) {
if(fc.getFilter().equals("duration")) {
Predicate ps = cb.greaterThanOrEqualTo(ticket.get(queryCondition.getDurationField()), fc.getFilterlist()[0]);
Predicate pe = cb.lessThan(ticket.get(queryCondition.getDurationField()), fc.getFilterlist()[1]);
predicatessub.add(cb.and(ps,pe));
}else
{
List<Predicate> predicates = new ArrayList<>();
for(int i=0; i<fc.getFilterlist().length; i++) {
Predicate p = cb.equal(ticket.get(fc.getFilter()),fc.getFilterlist()[i]);
predicates.add(p);
}
predicatessub.add(cb.or(predicates.toArray(new Predicate[predicates.size()])));
}
}
query.select(ticket)
.where(cb.and(predicatessub.toArray(new Predicate[predicatessub.size()])));
return entityManager.createQuery(query)
.getResultList();
}
QueryCondition.class
public class QueryCondition {
private List<FilterConditions> filterCondition;
private String durationField;
}
FilterConditions.class
public class FilterConditions {
private String filter;
private String[] filterlist;
}
Now I would like to build a quite more complex query involving joins and group by. Below is the sample query like what I would like to build using predicate.
SELECT
YEAR(pt.created_date),
MONTH(pt.created_date),
pt.assigned_team,
COUNT(tk.ticket_id)
FROM
(SELECT
*
FROM
tickets
WHERE
ticket_id IN (SELECT
ticket_id
FROM
Tickets
WHERE
resolved_date >= '2020-02-01')
AND resolved_date < '2020-05-01'
and assigned_team IN ('A' , 'B', 'C')) pt
LEFT JOIN
(SELECT
*
FROM
tickets
WHERE
status IN ('Closed','Resolved','New')
AND assigned_to IN ('ram','govind','ajith')) tk ON tk.ticket_id = pt.ticket_id
GROUP BY YEAR(pt.created_date) , MONTH(pt.created_date), pt.assigned_team order by
pt.assigned_team,YEAR(pt.created_date),MONTH(pt.created_date) asc;
Kindly advise how this can be achieved with Predicate or is there any other simpler way than Predicate.
Maybe this works:
First create a list with all field your model but removing associations. After pass this list in CriteriaQuery.
List<Expression<?>> groupByList = new ArrayList<>();
// ticket => Root<Tickets>
ticket.getModel().getAttibutes().stream()
.filter(a -> !a.isAssociation())
.forEach(a -> groupByList.add(ticket.get(a.getName())));
query.select(ticket)
.where(cb.and(predicatessub.toArray(new Predicate[predicatessub.size()])))
.groupBy(groupByList); // <== add group by
If you have join just do the same thing creating a cast with object EntityTypeImpl<?>. ex:
// import org.hibernate.metamodel.model.domain.internal.EntityTypeImpl
// join => Join<?,?>
((EntityTypeImpl<MyEntity>) join.getModel())
.getDeclaredAttributes().stream()
.filter(a -> !a.isAssociation())
.forEach(a -> groupByList.add(join.get(a.getName())));

Implementing a join in doctrine query builder not working correctly

I am trying to get information from one table based on information in another table, which is linked by an ID.
The two tables are: property and unit.
I need to gather all the units within a property but ONLY if the property has a status of '1' and a hidden flag of '0'. In normal mySQL, I wrote:
SELECT u.* FROM unit u INNER JOIN property p ON p.id = u.property WHERE p.status = 1 AND p.hidden = 0
which produces the correct results, although when I try the same using querybuilder:
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('u')
->from('AppBundle:Unit', 'u')
->join('u', 'AppBundle:Property', 'p', 'u.property = p.id')
->where('p.status = :status')
->andWhere('p.hidden = :hidden')
->setParameter('status', 1)
->setParameter('hidden', 0);
return $qb->getQuery()->getResult();
Using information I gleaned from the Doctrine Query Builder documentation. However, when I load the page I get the following error:
[Semantical Error] line 0, col 42 near 'u AppBundle:Property': Error:
Class 'u' is not defined.
The query being executed:
SELECT u FROM AppBundle:Unit u INNER JOIN u AppBundle:Property P u.property = p.id WHERE p.status = :status AND p.hidden = :hidden
Can anyone help figure out what I'm doing wrong in my query?
try to change this:
->join('u', 'AppBundle:Property', 'p', 'u.property = p.id')
to this:
->join('AppBundle:Property', 'p', 'WITH', 'u.property = p.id')
You should exchange your first and second arguments places, because join() method is:
/**
* Creates and adds a join over an entity association to the query.
*
* The entities in the joined association will be fetched as part of the query
* result if the alias used for the joined association is placed in the select
* expressions.
*
* <code>
* $qb = $em->createQueryBuilder()
* ->select('u')
* ->from('User', 'u')
* ->join('u.Phonenumbers', 'p', Expr\Join::WITH, 'p.is_primary = 1');
* </code>
*
* #param string $join The relationship to join.
* #param string $alias The alias of the join.
* #param string|null $conditionType The condition type constant. Either ON or WITH.
* #param string|null $condition The condition for the join.
* #param string|null $indexBy The index for the join.
*
* #return QueryBuilder This QueryBuilder instance.
*/
public function join($join, $alias, $conditionType = null, $condition = null, $indexBy = null)
This is a doc from doctrine QueryBuilder class.

Counting rows for the column in mysql

My problem is simple. I have two tables
transaction_bodies
------------------
body_id
full_name
and the other one is
transaction_accounts
--------------------
account_id
body_id
account_name
Relation is one to many. One body can have multiple accounts. I am trying to create a query that counts the accounts that bodies have.
I tried this
SELECT *
FROM
(
SELECT count(*) as trans, tb.full_name
FROM transaction_accounts ta
LEFT JOIN transaction_bodies tb
ON tb.body_id = ta.body_id
) as row;
But this doesn't give the right result. Can anyone help me out with this?
And if can provide how to write sub-queries in Laravel that would be a appreciated much.
Try this :
$result = DB::table('transaction_bodies')
->leftJoin('transaction_accounts as
ta','transaction_bodies.body_id','ta.body_id')
->select(DB::raw('count(ta.account_id) AS trans'),'transaction_bodies.full_name')
->groupBy('transaction_bodies.body_id')
->get();
You can do it with LEFT JOIN, e.g.:
SELECT tb.body_id, COUNT(ta.*)
FROM transaction_bodies LEFT JOIN transaction_accounts ta
ON tb.body_id = ta.body_id
GROUP BY tb.body_id;
With a simple LEFT JOIN you can achieve it like
SELECT tb.full_name, COUNT(account_id) as accounts
FROM transaction_bodies tb LEFT JOIN transaction_accounts ta
ON tb.body_id = ta.body_id
GROUP BY tb.body_id;
In Laravel you can do it like with model
$accounts = Transaction_body::leftJoin('transaction_accounts as ta','transaction_bodies.body_id','ta.body_id')->groupBy('transaction_bodies.body_id')->get();
without model
$accounts = DB::table('transaction_bodies')->leftJoin('transaction_accounts as ta','transaction_bodies.body_id','ta.body_id')->groupBy('transaction_bodies.body_id')->get();
/**
* Class Body
*/
class Body extends Model
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'transaction_bodies';
/**
* Get the accounts for the Transaction Body.
*/
public function accounts()
{
return $this->hasMany(Account::class);
}
}
/**
* Class Account
*/
class Account extends Model
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'transaction_accounts';
/**
* Get the body that owns the account.
*/
public function body()
{
return $this->belongsTo(Body::class);
}
}
//usage
$accounts = Body::find(1)->accounts;
https://laravel.com/docs/5.4/eloquent-relationships#one-to-many

Joins in laravel 5.3 in simple and Eloquent

I want to add some extra filter in my left join but I don't know how so kindly help me.And also tell me how can make this query in Eloquent. My query is given below:
select * from `users`
join `halls` on `halls`.`user_id` = `users`.`id`
left join `bookings` on `bookings`.`hall_id` = `halls`.`id` AND month(`bookings`.`date`) = 2 and day(`bookings`.`date`) = 4 and year(`bookings`.`date`) = 2017
join `user_role` on `user_role`.`user_id` = `users`.`id`
join `roles` on `roles`.`id` = `user_role`.`role_id`
where
`roles`.`id` = 2 AND
(`bookings`.`id` is null OR `bookings`.`status` = 0 )
group by users.id
user and role has many to many relation, user and hall one to many and hall and bookings has also one to many relation
User Model Relation
/**
* Many-to-Many relations with Role.
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function roles(){
return $this->belongsToMany(Role::class, 'user_role', 'user_id', 'role_id')->select('roles.name');
}
/**
* One-to-Many relations with halls.
*
* #return \Illuminate\Database\Eloquent\Relations\hasMany
*/
public function halls(){
return $this->hasMany(Hall::class);
}
Hall Model relation
public function user(){
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function bookings(){
return $this->hasMany(Booking::class);
}
Booking Model Realtion
public function hall(){
return $this->belongsTo(Hall::class)->distinct();
}
I dont know why you want to use group by without any aggregate function . Your ORM looks like below
Users::join('halls', 'users.id', '=', 'halls.user_id')
leftJoin('bookings', function($join){
$join->on('halls.id', '=', 'bookings.hall_id');
$join->on(DB::raw('month(`bookings`.`date`) = 2 and day(`bookings`.`date`) = 4 and year(`bookings`.`date`) = 2017'));
})
->join('user_role', 'users.id', '=', 'user_role.user_id')
->join('roles', 'roles.id', '=', 'user_role.role_id')
->whereRaw('where
`roles`.`id` = 2 AND
(`bookings`.`id` is null OR `bookings`.`status` = 0 )')->get();

Doctrine - Empty leftJoin SQL

I built the following Parts of my Entities :
/**
* #var Application_Model_Ticket
*
* #OneToMany(targetEntity="Application_Model_Ticket",mappedBy="contacts_id")
* #JoinColumn(name="id", referencedColumnName="contacts_id")
*/
private $tickets;
public function getTickets() {
return $this->tickets;
}
/**
* #var Application_Model_Contact
*
* #ManyToOne(targetEntity="Application_Model_Contact",cascade={"persist"})
* #JoinColumn(name="contacts_id", referencedColumnName="id")
*/
private $contact;
public function getContact() {
return $this->contact;
}
When I now try the following Doctrine Code :
$this->oQueryBuilder->select('contact','ticket')
->from('Application_Model_Contact', 'contact')
->leftJoin('contact.tickets', 'ticket')
->orderBy('contact.id', 'DESC');
I get a MYSQL-Error.
The following happens :
FROM contact c0_ LEFT JOIN ORDER BY c0_.id DESC
It seems that Doctrine doesn't fill in the LEFT JOIN properly.
Does anybody have an idea, why this happens ?
UPDATE:
->leftJoin('contact.tickets', 'ticket', 'WITH','contact.id = ticket.contactsId')
Gives me
LEFT JOIN AND (c0_.id = t1_.contacts_id)
you miss the ON in your query
$this->oQueryBuilder
->select('contact','ticket')
->from('Application_Model_Contact', 'contact')
->leftJoin('contact', 'on contact.ticket=Application_Model_Contact.field')
->orderBy('contact.id', 'DESC');
where Application_Model_Contact.field replace it for the match field to apply the JOIN
so your query should be like:
....FROM contact c0_ LEFT JOIN ON table1.field=table2.field ORDER BY c0_.id DESC
Source: http://oldforum.symfony-project.org/index.php/m/69061/
Mysql Join: http://dev.mysql.com/doc/refman/5.0/en/join.html
Try this:
$this->oQueryBuilder->select('contact','ticket')
->from('Application_Model_Contact', 'contact')
->leftJoin('contact.tickets', 'ticket', 'WITH', 'contact.id = ticket.contacts_id')
->orderBy('contact.id', 'DESC');