Doctrine DQL - Expected end of string, got 'inner' - mysql

I'm trying to perform kinda simple query, but I always get this exception
[Syntax Error] line 0, col 157: Error: Expected end of string, got
'inner'
Here's my query:
public function hasRecord($user, $event)
{
$q = $this->getEntityManager()->createQuery("
select count(h.id) from Tsk\FEBundle\Entity\History h
inner join h.user u where u.id = :user
inner join h.event v and v.id = :event
");
$q->setParameters([
"user" => $user,
"event" => $event
]);
return $q->getSingleScalarResult();
}
How can I perform two inner joins ? Is there something wrong with my query ?

You should do your joins before where clause:
public function hasRecord($user, $event)
{
$q = $this->getEntityManager()->createQuery("
select count(h.id) from Tsk\FEBundle\Entity\History h
inner join h.user u
inner join h.event v
where u.id = :user
and v.id = :event
");
$q->setParameters([
"user" => $user,
"event" => $event
]);
return $q->getSingleScalarResult();
}

Related

How to implement ON ( ... OR ...) mysql query in doctrine2 queryBuilder

I have a SQL query in MYSQL:
For example
SELECT s.* FROM vplanning.cities as c1
INNER JOIN vplanning.cities as c2
ON (c1.id = c2.area_id)
INNER JOIN vplanning.storages as s
ON (s.city_id = c2.id OR s.city_id = c1.id)
WHERE c1.id = 109;
In doctrine I can write something like this (from my work code):
$query = $em->getRepository('VplanningPageBundle:Storage')
->createQueryBuilder('s')
->innerJoin('s.city', 'c1')
->innerJoin('c1.area', 'c2')
->innerJoin('s.storagestype', 'st')
->where('c2.id = :cityID')
->andWhere('st.typename = :storagesTypeName')
->andWhere('s.active = :active')
->setParameters(array(
'cityID' => $cityID,
'storagesTypeName' => $storagesTypeName,
'active' => 1
))
->orderBy('s.adress')
->getQuery();
As you can see, I show my relation in
->innerJoin('s.city', 'c1')
but I need also relation like
->innerJoin('s.city', 'c2')
with this condition:
ON (s.city_id = c2.id OR s.city_id = c1.id)
But it throws this error:
Error: 'c2' is already defined
c1 and c2 are the same entity and have a inner relation.
Try this:
$repository = $em->getRepository('VplanningPageBundle:Storage');
$qb = $repository->createQueryBuilder('storage');
//We can now use the expr()
$qb->join('storage.city', 'city', Join::WITH)
->join('city.area', 'area', Join::WITH, $qb->expr()->eq('area.id', ':cityID'))
->join('storage.storagestype', 'type', Join::WITH, $qb->expr()->eq('type.typename', ':storagesTypeName'))
->where('storage.active = :active')
->setParameters(array(
'cityID' => $cityID,
'storagesTypeName' => $storagesTypeName,
'active' => 1
))
->orderBy('storage.adress');
$query = $qb->getQuery();
Try smth like this
$qb = $this->getRepository('VplanningPageBundle:City')->createQueryBuilder('c');
$qb->leftJoin('c.area', 'a')
->join('c.storage', 's', Join::ON, $qb->expr()->orX($qb->expr()->eq('c.id', 's.id'), $qb->expr()->eq('a.id', 's.id')))
->innerJoin('s.storagestype', 'st')
->where('c.id = :cityID')
->andWhere('st.typename = :storagesTypeName')
->andWhere('s.active = :active')
->setParameters(array(
'cityID' => $cityID,
'storagesTypeName' => $storagesTypeName,
'active' => 1,
))
->orderBy('s.adress')
->getQuery()
;
The solution of the problem was very difficult as for me, I have to study it :)
This is a answer for my question from some forum board:
$qb = $em->getRepository('VplanningPageBundle:Storage')->createQueryBuilder('storage');
$query = $qb->join('storage.city', 'city1', Join::WITH)
->leftJoin('city1.area', 'area', Join::WITH, $qb->expr()->eq('area.id', ':cityID'))
->leftJoin('storage.city', 'city2', Join::WITH, $qb->expr()->eq('city2.id', ':cityID'))
->join('storage.storagestype', 'type', Join::WITH, $qb->expr()->eq('type.typename', ':storagesTypeName'))
->where('storage.active = :active')
->andWhere($qb->expr()->orX($qb->expr()->isNotNull('city2'), $qb->expr()->isNotNull('area')))
->setParameters(array(
'cityID' => $cityID,
'storagesTypeName' => $storagesTypeName,
'active' => 1
))
->orderBy('storage.adress')
->getQuery();

How to specify multiple condition in Join statement rather than in Where block in NHibernate QueryOver

The following QueryOver generates the Subquery in the Where block but i was rather looking for the way to specify that condition on the join statement
var productsWithLatestComments = _sessionHelper.GetSession().QueryOver(() => p)
.Left.JoinAlias(() => p.Comments, () => cm)
.WithSubquery.Where(() => cm.CommentDate == QueryOver.Of<Comment>()
.Where(c => c.Product.Id == p.Id)
.SelectList(list => list.SelectMax(c => c.CommentDate)).As<DateTime>())
.Where(() => p.Status != "NOT SOLD" )
.SelectList(list => list ....GET THE LIST OF COLS.........
This GENERATES something like
SELECT this_.id as y0_, ......... FROM product this_
left outer join comment cn1_ on this_.id=cn1_.product_id
WHERE cn1_.comment_date = (SELECT max(this_0_.created_date) as y0_ FROM comment this_0_ WHERE this_0_.product_id = this_.id) and (not (this_.status = ?p0);?p0 = 'Sold Out'' [Type: String (18)]
But i was looking for
SELECT this_.id as y0_, ......... FROM product this_
left outer join comment cn1_ on this_.id=cn1_.product_id and cn1_.comment_date = (SELECT max(this_0_.created_date) as y0_ FROM comment this_0_ WHERE this_0_.product_id = this_.id)
WHERE (not (this_.status = ?p0);?p0 = 'Sold Out'' [Type: String (18)]
Ok i got it with some changes in the QueryOver by specifying the subquery inside the join alias rather than inside .WithSubquery
var productsWithLatestComments = _sessionHelper.GetSession().QueryOver(() => p)
.JoinAlias(() => p.Comments, () => cm, JoinType.LeftOuterJoin, Subqueries.Where(() => cm.CommentDate == QueryOver.Of<Comment>()
.Where(c => c.Product.Id == p.Id)
.SelectList(list => list.SelectMax(c => c.CommentDate)).As<DateTime>()))
.Where(() => p.Status != "NOT SOLD" )
.SelectList(list => list ....GET THE LIST OF COLS.........

linq lambda composite key where and group by

what's the linq lambda expression for the following mysql query
Select Count(*), Users.BusinessName From Offers
inner join Users on Users.UserId = Offers.UserId
inner join RoleUsers on RoleUsers.User_UserId = Users.UserId
inner join Roles on Roles.RoleId = RoleUsers.Role_RoleId
where Roles.RoleName = 'Seller'
group by Users.BusinessName
Counts the Number of Offers and Groups it by the User's Name ( where the User is a seller).
public static List<CountsByUser> NoOffersByUserType()
{
List<Offer> offers;
using (MainDb ctx = new MainDb())
{
var role = ctx.Roles.FirstOrDefault(r => r.RoleName == "Seller");
List<User> users = role.Users.ToList();
offers= ctx.OfertaPret.Any(u => u.User == users).ToList();
//here is the problem u.User ==users
}
List<CountsByUser> requests = offers.GroupBy(o => o.User.BusinessName)
.Select(nl => new CountsByUser
{
name = nl.Key,
number = nl.Count()
})
.ToList();
return requests;
}
offers= ctx.OfertaPret.Include(u=>u.User)
.Where(u => u.User.Roles.Any(r => r.RoleName == "Seller")).ToList();

Wordpress query to inner join posts -> custom table -> post meta where metakey = metavalue

I need to join POSTS with CUSTOM TABLE and POSTMETA. I am keeping track of popular posts in the custom table but I only want posts returned that have a specific postmeta value.
I searched and could not find a tut.
Here is what I 'think' I should do... but it doesn't work when done by hand in phpmyadmin.
SELECT (post info) FROM posts p INNER
JOIN custom_table t ON p.ID = t.ID
INNER JOIN post_meta m ON p.ID = m.ID
WHERE m.metakey = 'mykey' AND
post_type = 'post' AND post_date <
'$now' AND post_date > '$lastmonth'
ORDER BY postcount DESC LIMIT 5");
Do I need to inner join the post meta as a separate sub query?
If I might suggest, try using WP_Query(). It'll be a bit clumsy, since you'll need to add a filter for the post date range and then remove it, but it'll otherwise be predictably functional without a three-layer SQL join.
<?php
include_once( "wp-config.php" );
function filter_date_range( $where = '' ) {
$lastmonth = date("Y-m-d 00:00:00", strtotime("-1 month"));
$where .= " and post_date<now() and post_date>'{$lastmonth}'";
return( $where );
}
add_filter( 'posts_where', 'filter_date_range' );
$q = new WP_Query(array(
"post_status" => "publish",
"post_type" => "post",
"posts_per_page" => 5,
"meta_query" => array(array(
"key" => "mykey",
"value" => "my_preferred_value"
))
));
remove_filter( 'filter_date_range' );
var_dump( $q->posts );
?>

CakePHP 3 - How do I use left joins in a query

I have the following query that works, but after talking to the client I realized I need left joins to get the desired results and I don't know how to do it.
This is my query:
$query = $this->AssetStatusAudits->find('all', [
'contain' => [
'AssetStatus',
'Users',
'Assets' => function ($q) {
return $q->contain([
'Employees',
'Sites'
]);
}
],
'conditions' => [
'AssetStatusAudits.created >' => $from,
'AssetStatusAudits.created <' => $to
]
]);
$query->select([
'createdDate' => 'date(AssetStatusAudits.created)',
'assetStatus' => 'AssetStatus.desc_en',
'firstName' => 'Users.first_name',
'lastName' => 'Users.last_name',
'count' => $query->func()
->count('*')
])
->group('date(AssetStatusAudits.created)', 'assetStatus.desc_en', 'users.last_name')
->order('Users.last_name', 'Users.created');
The above query generates this in cake:
SELECT date(AssetStatusAudits.created) AS `createdDate`,
AssetStatus.desc_en AS `assetStatus`,
Users.first_name AS `firstName`,
Users.last_name AS `lastName`,
(COUNT(*)) AS `count`
FROM asset_status_audits AssetStatusAudits
INNER JOIN asset_status AssetStatus ON AssetStatus.id = (AssetStatusAudits.asset_status_id)
INNER JOIN users Users ON Users.id = (AssetStatusAudits.user_id)
INNER JOIN assets Assets ON Assets.id = (AssetStatusAudits.asset_id)
LEFT JOIN employees Employees ON Employees.id = (Assets.employee_id)
INNER JOIN sites Sites ON Sites.id = (Assets.site_id)
WHERE (AssetStatusAudits.created > date('2016-01-13') AND AssetStatusAudits.created < date('2016-05-03'))
GROUP BY date(AssetStatusAudits.created)
ORDER BY Users.last_name
But this is the query that I need to add to cakePHP and I don't know how to do it:
SELECT
date(asset_tracking.asset_status_audits.created) as 'Date',
asset_tracking.asset_status.desc_en as 'Status',
asset_tracking.users.first_name as 'First Name' ,
asset_tracking.users.last_name as 'Last Name',
count(*)
FROM asset_tracking.asset_status_audits
LEFT OUTER JOIN asset_tracking.assets ON asset_tracking.asset_status_audits.asset_id = asset_tracking.assets.id
LEFT OUTER JOIN asset_tracking.asset_status ON asset_tracking.asset_status_audits.asset_status_id = asset_tracking.asset_status.id
LEFT OUTER JOIN asset_tracking.users ON asset_tracking.asset_status_audits.user_id = asset_tracking.users.id
LEFT OUTER JOIN asset_tracking.employees ON asset_tracking.assets.employee_id = asset_tracking.employees.id
LEFT OUTER JOIN asset_tracking.sites ON asset_tracking.assets.site_id = asset_tracking.sites.id
WHERE asset_tracking.asset_status_audits.created between date('2016-01-13') and date('2016-05-19')
group by
date(asset_tracking.asset_status_audits.created) ,
asset_tracking.asset_status.desc_en,
asset_tracking.users.last_name
ORDER BY asset_tracking.users.last_name, asset_tracking.users.created;