I have this query in SQL that's working fine:
SELECT tl.*
FROM table1 tl
INNER JOIN table2 tl2
ON tl.id = tl2.other_id
INNER JOIN
(
SELECT other_id, MAX(date) maxDATE
FROM table2
GROUP BY other_id
)
tlv2 ON tl2.other_id = tlv2.other_id AND
tl2.date = tlv2.maxDATE WHERE tl.access=0
ORDER BY tlv2.maxDATE DESC
Now the problem is, I cant seem to figure out how to translate this into the Doctrine query builer.
I have this:
$subquery = $this->getEntityManager()->getRepository(Table2::class)
->createQueryBuilder('tl2')
->select(array('other_id','MAX(date) maxDate'))
->groupBy('other_id')
->getDQL();
$qb = $this->createQueryBuilder('tl');
$qb->select('tl')
->innerJoin(Table2::class,'tl2','WITH','tl.id = tl2.other_id')
->innerJoin("(".$subquery.")",'tlv2','WITH','tl2.date = tlv2.maxDATE')
->where('tl.access = 0')
->orderBy('tlv2.maxDATE','DESC');
but it's giving me the error:
Subquery is not supported here
On the line where I put the $subquery variable.
I cant seem to figure out what I'm doing wrong here. What am I doing wrong?
as mentioned here if you are using the ORM then the mapping will fail, you can only run this without hydration, in case you are using the DBAL only it will work as you expect
If you would go for native query solution and still need a mapped result then you can use \Doctrine\ORM\EntityManager::createNativeQuery with \Doctrine\ORM\Query\ResultSetMapping
$sql = <<<SQL
SELECT tl.*
FROM table1 tl
INNER JOIN table2 tl2
ON tl.id = tl2.other_id
INNER JOIN
(
SELECT other_id, MAX(date) maxDATE
FROM table2
GROUP BY other_id
)
tlv2 ON tl2.other_id = tlv2.other_id AND
tl2.date = tlv2.maxDATE WHERE tl.access=0
ORDER BY tlv2.maxDATE DESC
SQL;
$rsm = new Query\ResultSetMapping();
$rsm->addEntityResult(Entity::class, 'e');
$rsm->addFieldResult('e','id', 'id');
$rsm->addFieldResult('e','date', 'createAt');
$result = $this->entityManager->createNativeQuery($sql, $rsm)->getResult();
Related
The following query runs just fine when I paste it into my SQL tool, but through Laravel, it returns zero rows.
$sql = "
SELECT main_query.* FROM (
SELECT
c.id,
c.name,
c.order,
cd.case,
(SELECT count(*) from logs cl
where
c.id = cl.id
and cl.status = 'OPEN'
) as cl_count,
sdsc.task
FROM `table` c
INNER JOIN `table2` cd ON (c.id = cd.id)
LEFT JOIN `table3` sdsc ON (c.id = sdsc.id)
WHERE
c.status = 'NEW'
GROUP BY c.id
ORDER BY cd.updated_at DESC
) main_query
where main_query.cl_count > 1
GROUP BY main_query.id
ORDER BY main_query.updated_at DESC
limit 0,20
";
Due to the complexity of the actual query, I cannot convert it wholly into an eloquent query, so I am executing it using DB::select(DB::raw($searchQuery));
If I remove where main_query.cl_count > 1, the query runs just fine. What is causing this to fail, and how do I rewrite the code?
Try below code, generated by https://sql2builder.github.io/
DB::query()->fromSub(function ($query) {
$query->from('table')
->select('table.id', 'table.name', 'table.order', 'table2.case', 'table3.task')
->on(function ($query) {
$query->where('table.id','=','table2.id');
})
->on(function ($query) {
$query->where('table.id','=','table3.id');
})
->where('table.status','=','NEW')
->groupBy('table.id')
->orderBy('','desc');
},'main_query')
->select('main_query.*')
->where('main_query.cl_count','>',1)
->groupBy('main_query.id')
->orderBy('','desc')
->get();
I am trying to pass following sql query to Doctrine:
SELECT id, name, count(*) FROM (SELECT r.id, r.name, f.timestamp FROM `food_log` as f inner join recipe as r on f.recipe_id = r.id WHERE f.user_id = 6 and timestamp > "2016-09-01" and recipe_id is not null group by f.timestamp, r.id) a GROUP BY a.id ORDER BY count(*) DESC
It should return me recipes with amount of how many times particular user was using single recipe from selected timestamp.
Now I am trying to do this with Doctrine 1.2 and Symfony 1.4, however I do not know how to make query from subquery, I was trying to do something like this
$subQuery = Doctrine_Query::create()
->select('r.id, r.name, f.timestamp')
->from('FoodLog f')
->innerJoin('f.Recipe r')
->where('f.user_id = ?', $userId)
->andWhere('timestamp > ?', "2016-09-01")
->andWhere('f.recipe_id is not null')
->andWhere('r.is_premium = ?', $premium)
->groupBy('f.timestamp, r.id')
->getSqlQuery();
$query = Doctrine_Query::create()
->select('id, name, count(*)')
->from($subQuery)
->groupBy('id')
->orderBy('count(*) DESC');
return $query->fetchArray();
Anybody know where I am wrong with it ?
Thanks a lot for any response !
Basically, you can't do nested queries in this version of Doctrine. I'd recommend using a raw SQL query via the doctrine connector:
$sql = 'SELECT id, name, count(*) FROM (SELECT r.id, r.name, f.timestamp FROM `food_log` as f inner join recipe as r on f.recipe_id = r.id WHERE f.user_id = 6 and timestamp > "2016-09-01" and recipe_id is not null group by f.timestamp, r.id) a GROUP BY a.id ORDER BY count(*)
DESC';
$conn = Doctrine_Manager::getInstance()->getCurrentConnection();
$result = $conn->execute($sql);
foreach($result as $data){
// do something
}
As you're not hydrating objects, you should find this works well.
How to perform this Query on Laravel?
SELECT *
FROM conversion t1
JOIN (SELECT report_id, MAX(id) id
FROM conversion
GROUP BY report_id ) AS t2
ON t1.id = t2.id AND t1.report_id = t2.report_id
I already read in Laravel Documentary and not find an anything,
I already try in SQL and working but I don't know how to perform this Query in Laravel.
Please help to resolve this, Thank You.
I think this is the correct solution for your question:
$subQuery = \DB::table('conversion')
->selectRaw('report_id, MAX(id) id')
->groupBy('report_id')
->toSql();
$data = \DB::table('conversion t1')
->join(\DB::raw('(' . $subQuery . ') as t2'), function ($join) {
$join->on('t1.id', 't2.id')
->on('t1.report_id', 't2.report_id');
}, null, null, '')
->get();
If you want to check the query of this one you can use ->toSql() instead of ->get() in the end.
The output is:
select *
from `conversion t1`
join (
select report_id, MAX(id) as id
from `conversion`
group by `report_id`
) as t2
on `t1`.`id` = `t2`.`id`
and `t1`.`report_id` = `t2`.`report_id`
Didnt have my IDE right now, but it should work this way:
$results = DB::select(DB::raw ('SELECT *
FROM conversion t1
JOIN (SELECT report_id, MAX(id) id
FROM conversion
GROUP BY report_id ) AS t2
ON t1.id = t2.id AND t1.report_id = t2.report_id'));
i'm trying to convert this SQl query to QueryBuilder but i can't do it.
SELECT a.id, a.category_name, cat.Count
FROM `categories` a
LEFT OUTER JOIN (
SELECT `categories`.`category_parent` , COUNT(*) AS Count
FROM `categories`
GROUP BY category_parent
)
cat ON a.id = cat.category_parent
WHERE a.category_parent = 1
for example:
DB::table('users')
->join('contacts',DB::raw("a.id = cat.category_parent"),function($query){
$query->select(DB::raw("`categories`.`category_parent` , COUNT( * ) AS Count"))
->from('contacts')
->groupBy('category_parent')
->where(DB::raw("a.category_parent = 1"))
->get();
how to fix this method in laravel. thanks
Try getting the PDO instance to execute your query directly:
$PDO=DB::connection('mysql')->getPdo();
$stmt=$PDO->prepare("
SELECT a.id, a.category_name, cat.Count
FROM `categories` a
LEFT OUTER JOIN (
SELECT `categories`.`category_parent` , COUNT(*) AS Count
FROM `categories`
GROUP BY category_parent
)
cat ON a.id = cat.category_parent
WHERE a.category_parent = :category_parent
");
$stmt->bindParam(':category_parent', 1);
$stmt->execute();
$result = $stmt->fetchAll();
I have a query like that in one of my projects running on laravel 4.
Good Luck!
I have 2 tables.
table 1 (projects): id, name, type
table 2 (project_ratings): project_id, rating
Some projects don't have ratings.
SELECT `p`.`id`, `p`.`name`, AVG(pr.rating) FROM (`projects` p) JOIN `project_ratings` pr ON `p`.`id` = `pr`.`project_id` WHERE `p`.`type` = 'group' OR `p`.`type` = 'user';
I want to return all projects, and return NULL if there aren't any ratings. This query returns only the ones with ratings.
I tried left join, right join, full join, still same thing.
Using CodeIgniter Active Records:
$this->db->select("p.id, p.name, AVG(pr.rating)");
$this->db->from('projects p');
$this->db->join('project_ratings pr', 'p.id = pr.project_id');
$this->db->where('p.type', 'group');
$this->db->or_where('p.type', 'user');
$res = $this->db->get();
what am I missing?
When using an aggregate function (AVG() in this case), you need to specify a GROUP BY clause with the non-aggregate fields, eg
GROUP BY p.id, p.name
To ensure all project references are present regardless of joined ratings, use a LEFT JOIN.
The sql that you want would be
SELECT *
FROM projects
LEFT OUTER JOIN project_ratings ON projects.id = project_ratings.project_id
I'm not certain how to do that with code igniter.
Try this:
$this->db->select("p.id, p.name, AVG(pr.rating) as average_rating");
$this->db->from('projects p');
$this->db->join('project_ratings pr', 'p.id = pr.project_id', 'left');
$this->db->where('p.type', 'group');
$this->db->group_by('p.id');
$this->db->or_where('p.type', 'user');
$res = $this->db->get();
If there is no rating, average_rating will be NULL.
Query should be:
SELECT `p`.`id`, `p`.`name`, AVG(pr.rating)
FROM (`projects` p)
LEFT OUTER JOIN `project_ratings` pr ON `p`.`id` = `pr`.`project_id`
WHERE `p`.`type` = 'group' OR `p`.`type` = 'user';
(I don't know how to do that in CodeIgniter :)
You can get an outer join by do this:
$this->db->join('project_ratings pr', 'p.id = pr.project_id', 'outer');