Sub Query at join not coming in right way - mysql

Hiii, Currently I am stuck with a problem. I am finding no way to remove quotes generated by the zend on query generation of a sub query which is placed in a join operation.
The $selectInnerQuery creates the sub query which is used in the join operation this is called as inneranswer table. This is used to join with answer table. $select is used for the final query. Please help me on this...
$selectInnerQuery= $sql->select()->from(array('answer' => 'tblanswer'))->columns(array('aid' => new Expression('answer.aid'),'count' => new Expression('count(answer.qid)')));
$innerstatement = $sql->getSqlStringForSqlObject($selectInnerQuery);
$select = $sql->select()->from(array('answer' => 'tblanswer'))->columns($fieldsToSelect);
$select->join(array('inneranswer' => $innerstatement), 'inneranswer.aid = answer.aid', array(),'inner');
The query that I am getting from zend is
SELECT `answer`.* FROM `tblanswer` AS `answer`
inner join `SELECT answer.aid AS ``aid``, count(answer.qid) AS ``count`` FROM ``tblanswer`` AS ``answer`` WHERE answer.qid !=0 GROUP BY answer.qid, answer.baid` AS `inneranswer` ON `inneranswer`.`aid` = `answer`.`aid`
I have tried new Expression but it does not work in join operation.

When you are specifying your $innerstatement on joining, specify as like "{$innerstatement}", this may solve your quotes problem and also check your inner statement query returns sql query or it returns as object.

Came across the same issue today. Join table array should contain Select object instead of select query.
$selectObj = $sql->select()->from(array('answer' => 'tblanswer'))->columns(array('aid' => new Expression('answer.aid'),'count' => new Expression('count(answer.qid)')));
$select = $sql->select()->from(array('answer' => 'tblanswer'))->columns($fieldsToSelect);
$select->join(array('inneranswer' => $selectObj), 'inneranswer.aid = answer.aid', array(),'inner');

Related

Union of two tables in Zend 2

I want to union two tables with where clause in zf2:-
table1 app_followers
table2 app_users
where condition could be anything
and order by updated_date.
Please let me know the query for zend 2.
Thanks..
Using UNION is ZF2:
Using ZF2 dedicated class Combine Zend\Db\Sql\Combine
new Combine(
[
$select1,
$select2,
$select3,
...
]
)
A detailed example which uses combine is as follows:
$select1 = $sql->select('java');
$select2 = $sql->select('dotnet');
$select1->combine($select2);
$select3 = $sql->select('android');
$selectall3 = $sql->select();
$selectall3->from(array('sel1and2' => $select1));
$selectall3->combine($select3);
$select4 = $sql->select('network');
$selectall4 = $sql->select();
$selectall4->from(array('sel1and2and3' => $selectall3));
$selectall4->combine($select4);
$select5 = $sql->select('dmining');
$selectall5 = $sql->select();
$selectall5->from(array('sel1and2and3and4' => $selectall4));
$selectall5->combine($select5);
which is equivalent to the normal SQL query for UNION:
SELECT * FROM java
UNION SELECT * from dotnet
UNION SELECT * from android
UNION SELECT * from network;
UNION SELECT * from dmining;
I hope it helps.
I wanted to do a similar task and spent a lot of time while to figure out how to do that in the right way.
The idea with Laminas\Db\Sql\Combine is really well but you cannot apply the ordering to this object and as the result, it's useless in this case.
Finally, I ended up with the next code:
$skill = $sql->select('skill');
$language = $sql->select('language');
$location = $sql->select('location');
$occupation = $sql->select('occupation');
$skill->combine($language);
$language->combine($location);
$location->combine($occupation);
$combined = (new Laminas\Db\Sql\Select())
->from(['sub' => $skill])
->order(['updated_date ASC']);
However, it's a bit messy with parentheses. If it's a matter for you, please check this comment on Github, but on MySQL id doesn't matter, not sure about other databases.

JOIN two SELECTs with Doctrine

I need to write this query with Doctrine. How can I write it down using QueryBuilder?
SELECT charges.id, charges.currency, charges.total_transactions,
charges.total_volume, charges.commission, refunds.total_payouts
FROM
(SELECT ...very long query...) charges
LEFT JOIN
(SELECT ...very long query...) refunds
ON charges.id = refunds.id AND charges.currency = refunds.currency
You can use Native SQL and map results to entities:
use Doctrine\ORM\Query\ResultSetMapping;
$rsm = new ResultSetMapping;
$rsm->addEntityResult('AppBundle:Charges', 'charges')
->addEntityResult('AppBundle:Refunds', 'refunds')
->addFieldResult('charges', 'id', 'id')
->addFieldResult('charges', 'currency', 'currency')
->addFieldResult('charges', 'total_transactions', 'total_transactions')
->addFieldResult('charges', 'total_volume', 'total_volume')
->addFieldResult('charges', 'commission', 'commission')
->addFieldResult('refunds', 'total_payouts', 'total_payouts')
;
$sql = "
SELECT
charges.id,
charges.currency,
charges.total_transactions,
charges.total_volume,
charges.commission,
refunds.total_payouts
FROM
(SELECT ...very long query...) charges
LEFT JOIN
(SELECT ...very long query...) refunds ON charges.id = refunds.id AND charges.currency = refunds.currency
WHERE some_field = ?
";
$query = $this->getEntityManager()->createNativeQuery($sql, $rsm);
$query->setParameter(1, $name);
$entities = $query->getResult();
You can use DQL like this:
$dql = "SELECT ...";
$q = $entityManager->createQuery($dql)->setParameters($arrayParameters);
$result = $q->execute();
or QueryBuilder for each sub-query, like:
// subquery 1
$subQuery1 = $entityManager->createQueryBuilder()
->select('...')
->from('...')
->getDQL()
;
// subquery 2
$subQuery2 = ...
// etc
// ...
// main query
$query = $entityManager->createQueryBuilder()
->select('...')
->from('...', $subQuery1)
->leftJoin('...', $subQuery1->getDQL()),
->where()
;
PS: I just try provide gist for you... hope now you have clue...
Now I found out that it's impossible.
Comment created by stof:
DQL is about querying objects. Supporting subselects in the FROM clause means that the DQL parser is not able to build the result set mapping anymore (as the fields returned by the subquery may not match the object anymore).
This is why it cannot be supported (supporting it only for the case you run the query without the hydration is a no-go IMO as it would mean that the query parsing needs to be dependant of the execution mode).
In your case, the best solution is probably to run a SQL query instead (as you are getting a scalar, you don't need the ORM hydration anyway)
Source: https://github.com/doctrine/doctrine2/issues/3542

Convert sql query with a join on a subselect to a linq statement

I am trying to convert the following sql query to LINQ statement
SELECT t.*
FROM (
SELECT Unique_Id, MAX(Version) mversion
FROM test
GROUP BY Unique_Id
) m INNER JOIN
test t ON m.Unique_Id = t.Unique_Id AND m.mversion = t.Version
LINQ statement
var testalt = (from altt in CS.test
group altt by altt.Unique_Id into g
join bp in CS.alerts on g.FirstOrDefault().Unique_Id equals bp.Unique_Id
select new ABCBE
{
ABCName= bp.Name,
number = bp.Number,
Unique_Id = g.Key,
Version = g.Max(x=>x.Version)
});
I am getting an error of where clause. Please help
SQL FIDDLE
This is not an easy straight forward conversion but you can accomplish the same thing using linq method syntax. The first query is executed to an expression tree, then you are joining that expression tree from the grouping against CS.alerts. This combines the expression tree from CS.test query into the expression tree of CS.alerts to join the two expression trees.
The expression tree is evaluated to build the query and execute said query upon enumeration. Enumeration in this case is the ToList() call but anything that gets a result from the enumeration will execute the query.
var query1 = CS.test.GroupBy(x => x.Unique_Id);
var joinResult = CS.alerts.Join(query1,
alert => new { ID = alert.Unique_Id, Version = alert.Version },
test => new { ID = test.Key, Version = test.Max(y => y.Version },
(alert, test) => new ABCBE {
ABCName = alert.Name,
number = alert.Number,
Unique_Id = test.Key,
Version = test.Max(y => y.Version)
}).ToList();
Because query1 is still an IQueryable and you are using CS.alerts (which I'm guessing CS is your data context) it should join and build the query to execute upon the ToList() enumeration.

cakePHP: updating mysql table using WHERE clause with multiple conditions

I want to write this SQL statement in cakePHP syntax:
UPDATE students SET status = 'graduated' WHERE age = '23' AND major = 'math';
Now, the way I am trying to do this in cake is
$student->updateAll( array('Student.status' => "'".$rowdata."'"),
array('Student.age' => $current_highest_age,'Student.major' =>
"'".$major."'"));
My variables: $rowdata = 'graduated'; $current_highest_age = 23; and $major = 'math'.
The table is not being updated. Is there a problem with my syntax? I will appreciate your help.
UPDATE ON THE QUESTION:
Actually, I found out where I was wrong in my syntax. The cake code should be 'Student.major' => $major instead of 'Student.major'=>"'".$major."'"
You are double escaping
updateAll expects the fields to be SQL expressions (or simply quoted strings) but the conditions should not be. As such, the query you're going to be generating right now is:
UPDATE
students
SET
status = 'graduated'
WHERE
age = '23' AND
major = '\'math\''
To prevent the extra quotes, which will cause the syntactically-valid statement to match 0 rows, just let Cake take care of your conditions for you as with other methods:
$student->updateAll(
array('Student.status' => "'".$rowdata."'"),
array(
'Student.age' => $current_highest_age,
'Student.major' => $major
)
);
Easy way to update a field of a Model
$this->Testing->updateAll(
array('Testing.door_open_close' => $door_open_close), // value that is updated
array('Testing.id' => $zoneId) // condition field of a Model
);
UPDATE students ...
^^^^^^^^--- student WITH an S
v.s.
array('Student.age')
^^^^^^^ - student WITHOUT an S

ZF2 Inner join with where clause returns empty result

When I try the follow mysql query in send I just get back an empty results set (who suposed to be filled).
I tried the follow query in my mysql workbench (gives a results back)
SELECT `websites`.*, `s`.`website_id` AS `websites.id`
FROM `websites`
INNER JOIN `websites_statistics` AS `s` ON `s`.`website_id` = `websites`.`id`
WHERE `websites`.`website` = 'google.com' LIMIT 0,1
And this one in my ZF2 application (empty result set)
$sql = new Sql($this->tableGateway->getAdapter());
$select = $sql->select();
$select->from('websites')
->join(array('s' => 'websites_statistics'), 's.website_id = websites.id', array('websites.id' => 'website_id'), \Zend\Db\Sql\Select::JOIN_INNER)
->where(array('websites.website' => 'google.com'));
$resultSet = $this->tableGateway->selectWith($select);
echo $select->getSqlString();
return $resultSet;
Debug result:
SELECT "websites".*,
"s"."website_id" AS "websites.id"
FROM "websites"
INNER JOIN "websites_statistics" AS "s" ON "s"."website_id" = "websites"."id"
WHERE "websites"."website" = 'google.com'
(!updated) The query a bit so it's more easier. I think there goes something wrong at the first moment because I think "s"."website_id" AS "websites.id" has to flip in the other direction .. "websites.id" AS "s"."website_id" I need websites.id to take record by website_id from the websites_statistics table.
Thanks in advance!
Nick
I got it work. The problem wasn't the query it's self. I had to add the fields of the second table (to one I join) to the model (exchangeArray) of the first table! That did the trick. Thanks you all.