SubQueries in Laravel 4.2 - mysql

Can anyone teach me how can we use a query like this in Laravel 4.2
SELECT
t.Truck_Number,
t.Created_dt,
t.Latitude,
t.Longitude,
t.Speed,
t.Heading
FROM
truckgps t
INNER JOIN
(
SELECT
Truck_Number,
max(Created_dt) as MaxDate
FROM
truckgps
GROUP BY
Truck_Number
) tm
ON
t.Truck_Number = tm.Truck_Number AND
t.Created_dt = tm.MaxDate
this query is provided by someone else, can it be made better using laravel ?

Using Laravel Query builder - you can make like this :
$results = DB::select("SELECT
t.Truck_Number,
t.Created_dt,
t.Latitude,
t.Longitude,
t.Speed,
t.Heading FROM truckgps t
INNER JOIN
( SELECT Truck_Number, max(Created_dt) as MaxDate from truckgps group by Truck_Number )
tm on t.Truck_Number = tm.Truck_Number and t.Created_dt = tm.MaxDate");
or if you have parameters, than you can binding like this :
DB::select("select count(1) count from table t where t.id= ? and t.roles_id = ?",
array($id, $role_id)
);

If you have two tables...I have one solution for your question.. you dont need use joins for this. Table1 name 'truckgps' and table 2 name 'truckgpss' My Ans
$truckgps = DB::table('truckgps')->select('Truck_Number','Created','Latitude','Longitude','Speed','Heading ')->get();
foreach ($truckgps as $t)
{
$result = DB::table('truckgpss')->select('MAX(Created_dt) AS MaxDate ','Truck_Number')->where('MaxDate','=',$t->Created_dt )->where('Truck_Number','=',$t->Truck_Number)->groupBy('Truck_Number')
->get();
// if u need value convert array to string use another foreach loop here
foreach ($result as $value)
{
echo $value->Truck_Number; // now u can see the result truck no..
}
}
I think its help to u...Thank you ..

Related

How to convert this query to doctrine DQL

SELECT apntoken,deviceid,created
FROM `distribution_mobiletokens` as dm
WHERE userid='20'
and not exists (
select 1
from `distribution_mobiletokens`
where userid = '20'
and deviceid = dm.deviceid
and created > dm.created
)
What this query does is selects all mobiletokens where the user id is equal to 20 and the deviceid is the same but chooses the newest apntoken for the device.
My database looks like below.
For more information on this query, I got this answer from another question I asked here(How to group by in SQL by largest date (Order By a Group By))
Things I've Tried
$mobiletokens = $em->createQueryBuilder()
->select('u.id,company.id as companyid,user.id as userid,u.apntoken')
->from('AppBundle:MobileTokens', 'u')
->leftJoin('u.companyId', 'company')
->leftJoin('u.userId', 'user')
->where('u.status = 1 and user.id = :userid')
->setParameter('userid',(int)$jsondata['userid'])
->groupby('u.apntoken')
->getQuery()
->getResult();
//#JA - Get the list of all the apn tokens we need to send the message to.
foreach($mobiletokens as $tokenobject){
$deviceTokens[] = $tokenobject["apntoken"];
echo $tokenobject["apntoken"]."\n";
}
die();
This gives me the incorrect response of
63416A61F2FD47CC7B579CAEACB002CB00FACC3786A8991F329BB41B1208C4BA
9B25BBCC3F3D2232934D86A7BC72967A5546B250281FB750FFE645C8EB105AF6
latestone
Any help here is appreciated!
Other Information
Data with SELECT * FROM
Data after using the SQL I provided up top.
You could use a subselect created with the querybuilder as example:
public function selectNewAppToken($userId)
{
// get an ExpressionBuilder instance, so that you
$expr = $this->_em->getExpressionBuilder();
// create a subquery in order to take all address records for a specified user id
$sub = $this->_em->createQueryBuilder()
->select('a')
->from('AppBundle:MobileTokens', 'a')
->where('a.user = dm.id')
->andWhere('a.deviceid = dm.deviceid')
->andWhere($expr->gte('a.created','dm.created'));
$qb = $this->_em->createQueryBuilder()
->select('dm')
->from('AppBundle:MobileTokens', 'dm')
->where($expr->not($expr->exists($sub->getDQL())))
->andWhere('dm.user = :user_id')
->setParameter('user_id', $userId);
return $qb->getQuery()->getResult();
}
I did this for now as a temporary fix, not sure if this is best answer though.
$em = $this->em;
$connection = $em->getConnection();
$statement = $connection->prepare("
SELECT apntoken,deviceid,created
FROM `distribution_mobiletokens` as dm
WHERE userid=:userid
and not exists (
select 1
from `distribution_mobiletokens`
where userid = :userid
and deviceid = dm.deviceid
and created > dm.created
)");
$statement->bindValue('userid', $jsondata['userid']);
$statement->execute();
$mobiletokens = $statement->fetchAll();
//#JA - Get the list of all the apn tokens we need to send the message to.
foreach($mobiletokens as $tokenobject){
$deviceTokens[] = $tokenobject["apntoken"];
echo $tokenobject["apntoken"]."\n";
}

How to simplify this 2 MySQL Queries

This must be an easy one, but I can't remember how I did it before.
I'm trying to make another query within the query where record IDs are match:
/*
tables:
models:
model_id
model_name
models_years:
model_year_id
model_id
year
*/
$models = DBW::run('SELECT * FROM models', [], true);
$models_years = DBW::run('SELECT * FROM models_years', [], true);
$output = [];
foreach ($models as $model)
{
$years = [];
foreach ($models_years as $model_year)
{
if ($model_year['model_id'] == $model['model_id'])
{
$years[] = $model_year['year'];
}
}
$output[] = [
'model_name' => $model['model_name'],
'years' => $years
];
}
var_dump( $output );
I use PDO (settings: ATTR_DEFAULT_FETCH_MODE = FETCH_ASSOC), and "DBW::run" function returns $stmt->fetchAll().
this is just an example of what I'm trying to do or improve, I know it's possible to do all of that in a single SQL, I've done it before and can't remember! :(
SELECT m.model_name, y.`year`
FROM models AS m
LEFT JOIN models_years As y ON m.model_id = y.model_id
OR from your original question, the following might be what you need:
SELECT m.model_name, group_concat(y.`year`) AS `year`
FROM models AS m
LEFT JOIN models_years As y ON m.model_id = y.model_id
GROUP BY 1
Why?
1 - Join table to reduce SQL calls
2 - GROUP the result (BY 1 == BY m.model_name, just a lazy shorthand here)
3 - group_concat(...) will by default produce: year1,year2,year3,... and then you can use PHP explode(',', ...) to change to array if you need
Join the tables, and use GROUP_CONCAT to combine all the years for each model. Then use explode() to split that into an array.
$output = DBW::run('select m.model_name, GROUP_CONCAT(y.year) AS years
FROM models AS m
LEFT JOIN models_years AS y ON m.model_id = y.model_id
GROUP BY m.model_id', [], true);
foreach ($output as &$row) {
$row['years'] = explode(',', $row['years']);
}
SELECT model_name, year FROM models, models_years WHERE
models.model_id=models_years.model_id
Or, if you prefer the JOIN syntax,
SELECT model_name, year FROM models JOIN models_years ON
models.model_id=models_years.model_id
another way to do this is with the sub select.
select * from models where model_id in (select model_id from models_years)

How can I implement a multi join in Typo3 via userfunction?

I want to implement the following sql query:
SELECT title
FROM sys_category
JOIN sys_category_record_mm ON sys_category.uid = sys_category_record_mm.uid_local
JOIN tt_content ON sys_category_record_mm.uid_foreign = tt_content.uid
WHERE tt_content.uid = 645
If I execute this query directly via phpmyadmin it is working, but if I try the following via userfunction the content of $row is false, so I think the syntax for my multi join must be wrong. Hope you can help me :)
public function getCategories()
{
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery
(
'title',
'sys_category JOIN sys_category_record_mm ON sys_category.uid = sys_category_record_mm.uid_local JOIN tt_content ON sys_category_record_mm.uid_foreign = tt_content.uid',
'sys_category.uid = 645'
);
$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc( $res );
var_dump( $row );
}
My bad, the problem was, that I used
'sys_category.uid = 645'
instead of
'tt_content.uid = 645'

Left Join from Select Zend Framework

How can I do a Query like this using the Zend framework
SELECT * FROM `productos` AS `p`
LEFT JOIN (SELECT SUM(cantidad) AS transferencias FROM transferencias WHERE upc = p`.`upc` and sucursal = 10)
AS `trans` ON trans.upc = p.upc AND trans.sucursal_clave_destino = 10
Thank you in advance.
You need to try this one.
I can't try it but the way of resolve it you can use from my query
$this->getAdapter()
->select()
->from(array('p' => 'productos'))
->joinLeft(array('trans' => $this->getAdapter()
->select()
->from('transferencias', 'SUM(cantidad)')
->where('upc IN (?)', $this->getAdapter()
->select()
->from('productos', 'upc')
)->where('sucursal = ?', 10)
), 'trans.upc = p.upc')
->where('trans.sucursal_clave_destino = ?', 10)
->query()
->fetchAll();
First of all, I'm afraid it's impossible for your query to run because the syntax is wrong. The correct way to write it is:
SELECT *, SUM(trans.cantidad) as cantidad
FROM productos AS p
LEFT JOIN transferencias AS trans
ON p.upc = trans.upc
WHERE trans.sucursal_clave_destino = 10 AND trans.sucursal = 10
First approach
I assume you have created your model in this manner: http://framework.zend.com/manual/1.12/en/learning.quickstart.create-model.html
For example, in your Default_Model_ProductosMapper:
function getXXXX(){
$select = "[THE ABOVE QUERY]";
$result = $this->getDbTable()->getAdapter()->fetchAll($select);
return $result;
}
This is the most basic approach.
Second approach
By using Zend_Db functions, which is like prepare statement in database concept. Only use it to increase safety if you are passing parameters from user input (see SQL injection), otherwise it's safe to use the first approach.
Still, in your mapper:
function getXXXX(){
$query = $this->getDbTable()->getAdapter()->select();
$query->from('productos', array());
$query->joinLeft('transferencias', 'productos.upc = transferencias.upc', array('SUM(trans.cantidad) as cantidad));
$query->where("trans.sucursal_clave_destino = 10");
$query->where("trans.sucursal = 10");
// get result
$stmt = $this->getDbTable()->getAdapter()->query($query);
$result = $stmt->fetchAll();
return $result;
}
Third approach
If you are using Database ORM like Doctrine2, you can also write SQL or DQL (Doctrine Query Language) queries, which syntax is highly similar with SQL queries but absolutely NOT the same mechanism. The document is here. This document covers both approaches above for DQL and also will tell you where to put them.

Writing a custom mysql query to order wordpress users by a custom user meta field

Basically, I need to order a list of WordPress users by the city they live in. I've got a custom user meta field for city, and I've got the query working properly, but the query lists everyone who hasn't filled out a city at the beginning since it places blank fields at the beginning of the order.
What I need is to figure out how to only select and display users who have given a value other than blank in the city field. Unfortunately, I've found myself stumped.
Any thoughts on how to do this? Also, if anyone knows a way to orderby a custom user meta field using wp_user_query as opposed to this mess, I'm all ears.
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$limit = 10;
$offset = ($paged - 1) * $limit;
$key = 'city';
$sql = "SELECT SQL_CALC_FOUND_ROWS {$wpdb->users}.* FROM {$wpdb->users}
INNER JOIN {$wpdb->usermeta} wp_usermeta ON ({$wpdb->users}.ID = wp_usermeta.user_id)
INNER JOIN {$wpdb->usermeta} wp_usermeta2 ON ({$wpdb->users}.ID = wp_usermeta2.user_id)
WHERE 1=1
AND wp_usermeta.meta_key = 'wp_capabilities'
AND CAST(wp_usermeta.meta_value AS CHAR) LIKE '%\"subscriber\"%'
AND wp_usermeta2.meta_key = '$key'
ORDER BY wp_usermeta2.meta_value ASC
LIMIT $offset, $limit";
$site_users = $wpdb->get_results($sql);
$found_rows = $wpdb->get_var("SELECT FOUND_ROWS();");
foreach ($site_users as $site_user) {
// user info here
}
Try something like
...
WHERE 1=1
AND wp_whatever.name_of_city IS NOT NULL
AND LENGTH(wp_whatever.name_of_city) > 0
AND wp_usermeta.meta_key = 'wp_capabilities'
...