I would like to translate this $query using the find() method of the cakephp's ORM.
$custom_query = $this->Agency->query(
"SELECT a.id, a.name, a.created, c.total
FROM agencies a
join (SELECT agency_id, sum(price) total
FROM commands
GROUP BY agency_id) C
on a.id = c.agency_id;"
);
(This query does exactly what I want but I'd like to understand how to use cakephp ORM and $virtualFields)
Thank for your help and your time.
IF you are using CakePHP 1.3 or higher, you can define virtual fields in the model(i.e. calculated fields).
According to your query, I would define the virtual field in the model class like this:
$virtualFields = array(
'total'=>'(SELECT SUM(price) FROM commands WHERE agency_id = Agency.id)'
);
Then you can call that field as a regular ORM field:
$this->Agency->find('all',array(
'fields'=>array(
'id','name','created','total'
)
)
);
The Cake manual page : http://book.cakephp.org/2.0/en/models/virtual-fields.html
Related
Can't find any info on how to execute something like
WITH table AS (
SELECT colA, colB
FROM table2 INNER JOIN table1 ON table1.id = table2.colA
),
table4 AS (
SELECT moo, foo
INNER JOIN table3 ON table3.colC = table4.colD
),
......
using Laravel db query builder and the expression WITH
Does anybody have build such query and have clue how to be executed?
It's perfectly possible, I use it a lot.
For example, I have a $query and I have an array called $params (the prepared statements).
Than I do:
$connection = DB::connection('mysql');
$connection->getPdo()->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$result = $connection->select($query, $params);
I need the PDO::ATTR_EMULATE_PREPARES since I have repeating params (e.g. multiple times :user_id in the query).
So basically, I use a raw query. It is possible to also use such a query on an eloquent model, in which case it will return models as you are used to in Laravel. But this example really shows the basic version.
i have some query and i just know how to query on mysql (phpmyadmin)
i got information if using DB::select we cannot to use paginate, so we need change to DB::table(some query) to using pagination.
but the problem is i am confuse how to convert my query into DB::table(some query)
Here is my code
$daily = DB::select("
SELECT
employees.employee_name,
COUNT(DISTINCT DATE(attendance.attendance_datetime)) as jumlah,
locations.location_name,
TIME(MIN(attendance.attendance_datetime)) as check_in,
CASE
WHEN ISNULL(TIME(MIN(attendance.attendance_datetime))) THEN attendance_absence.remarks
WHEN TIME(MIN(attendance.attendance_datetime)) > '08:05:00' THEN (SELECT TIMEDIFF('08:05:00', MIN(TIME(attendance_datetime))))
WHEN TIME(MIN(attendance.attendance_datetime)) <= '08:05:00' THEN 'Good'
ELSE 'No Record'
END as detail_telat,
attendance_absence.remarks as remarks
FROM
employees
LEFT JOIN attendance ON employees.employee_name = attendance.attendance_name AND DATE(attendance.attendance_datetime) = '$date'
LEFT JOIN locations ON employees.location_id = locations.id
LEFT JOIN attendance_absence ON attendance_absence.employee_name = employees.employee_name AND attendance_absence.absences_date = '$date'
WHERE locations.location_name LIKE '%'
GROUP BY employees.employee_name
ORDER BY employees.employee_name
")->paginate(3);
please help me to convert my query into eloquent or query builder, or any suggestion ?
Currently, pagination operations that use a groupBy statement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually.
Check documentation
I would like to ask for your help with Doctrine2 DBAL query built with QueryBuilder. I'm used to ORM, but I think it's an overkill for such query which is being called in a listener.
I need a query with SELECT EXISTS and I don't know how I can construct it using DBAL QueryBuilder.
I have a subquery already created:
$subQuery = $connection->createQueryBuilder();
$subQuery
->select('o.id')
->from('order', 'o')
->leftJoin('o', 'payment', 'p')
->where($subQuery->expr()->isNull('p.id'))
;
I basically want to check if there are any unpaid orders. I now have no idea how to build the SELECT EXISTS query? Can anyone point me in the right direction? I was thinking about something like this:
$qb->select('EXISTS(?)')->setParameter($subQuery->getDQL())
Will that be the correct solution?
#EDIT
After a while of thinking I decided to use ORM instead. Unfortunately that did not work either, I'm getting an error:
line 0, col 7: Error: Expected known function, got 'EXISTS'
The DQL is:
SELECT EXISTS(<subquery here>)
It is a bit weird considering that It has been build with QueryBuilder:
/* #var $qb QueryBuilder */
$qb = $this->em->createQueryBuilder();
$qb
->select($qb->expr()->exists($subQuery->getDQL()));
A few years late, but you need to specify your EXISTS subquery SQL within the SELECT or WHERE statement portion of the QueryBuilder, as opposed to using a parameter.
Additionally since order is a reserved word in MySQL, you will need to use identifier quotes ` (back-tick) to escape the table name.
When using the ORM; you must specify a FROM statement that references an entity, so you would need to change your approach.
$connection = $this->em->getConnection();
$expr = $connection->getExpressionBuilder();
$qbSub = $connection->createQueryBuilder()
->select('1')
->from('`order`', 'o')
->leftJoin('o', '`payment`', 'p', $expr->eq('p.order_id', 'o.id'))
->where($expr->isNull('p.id'));
/**
* #return string "1" if a record exists, "0" otherwise
*/
$connection->createQueryBuilder()
->select('EXISTS(' . $qbSub->getSQL() . ')')
->execute()
->fetchColumn();
Resulting SQL
SELECT EXISTS(
SELECT 1
FROM `order` AS o
LEFT JOIN `payment` AS p
ON p.order_id = o.id
WHERE p.id IS NULL
);
Note: If you have any parameters, the values for the placeholders must be bound using QueryBuilder::setParameter() on the top-level
query, not the sub-queries.
$qbSub = $connection->createQueryBuilder()
->select('1')
->from('`order`', 'o')
->leftJoin('o', '`payment`', 'p', $expr->andX(
$expr->eq('p.order_id', 'o.id'),
$expr->eq('p.name', ':name') // subquery placeholder
))
->where($expr->isNull('p.id'));
$connection->createQueryBuilder()
->select('EXISTS(' . $qbSub->getSQL() . ')')
->setParameter('name', $value) // subquery placeholder param value
->execute()
->fetchColumn();
However, I suggest changing your query from an exclusion join to an inclusion join with NOT EXISTS. Doing so will filter orders that have been paid, out of your result-set. Instead of attempting to join every order on every payment and retrieve the payments that return null. Dramatically improving the performance of the query.
Example db-fiddle
SELECT EXISTS (
SELECT 1
FROM `order` AS o
WHERE NOT EXISTS(
SELECT NULL
FROM `payment` AS p
WHERE p.order_id = o.id
)
)
My query is :
SELECT * FROM drivers INNER JOIN vehicle ON drivers.vehicle_id = vehicle.id INNER JOIN cartype ON vehicle.cartype_id = cartype.id WHERE drivers.status = "free" AND vehicle.cartype_id = 1
Convert this query into laravel eloquent query .
I've tried harder but can't achieve !
Since we don't know what models and relationship between them you have - here is pure Query Builder request (pure translation of your sql, even if join with cartype table is redundant):
$result = DB::table("drivers")
->where("drivers.status", "free")
->join("vehicle", "drivers.vehicle_id", "=", "vehicle.id")
->join("cartype", "vehicle.cartype_id", "=", "cartype.id")
->where("vehicle.cartype_id", 1)->get()
Source: documentation, API page.
I have this query with subquery.
SELECT * FROM
(SELECT module_id FROM an_modules AS m LIMIT 20 OFFSET 0) AS m
LEFT JOIN an_module_sites AS ms ON (m.module_id = ms.module_id)
How to use DBAL to build subquery like this?
This doesn't seem to be work.
$qb->select('*')
->from(
$qb->select('module_id')
->from($this->Db->getTableName('modules'), 'm')
, 'm')
->leftJoin('m', $this->Db->getTableName('module_sites'), 'ms', 'm.module_id = ms.module_id');
$stmt = $qb->execute();
$result = $stmt->fetchAll();
I recently needed to do this to implement a pagination/sorting helper. As part of this I would take a querybuilder executed by my model and and generically count the total rows it would produce if unlimited.
To be cross platform I couldn't use rowCount and potential grouping meant I couldn't just change the fields in the select - so the best option was to remove the limits and count it as a subquery. This is what I came up with:
<?php
$totalResults = $qb->getConnection()->createQueryBuilder()
->select('COUNT(*)')
->from(
'('
.$qb
->setFirstResult(null)
->setMaxResults(null)
->resetQueryPart('orderBy')
->getSQL()
.')',
'tmp')
->execute()
->fetch(\PDO::FETCH_COLUMN);
I'm not sure how doctrine ORM handles this, but in pure DBAL at least this seems to work.