In common query, we can use select a record or a lot of records using query like this
SELECT * FROM tagihan_cleaning
WHERE YEAR("ditagihkan_bulan") = 2017 AND
MONTH("ditagihkan_bulan") = 06
Now, In yii2, I have a dateInput , which is 06-2017.
Then, How to use Activerecord just query above.So far, I wonder like this:
TagihanCleaning::find()->where([
'ditagihkan_bulan' => MONTH('ditagihkan_bulan')
])->all();
Please advise
Assuming you dateinput is string name $your_date_input, for an activeRecord, you could use
a liter where and binding
TagihanCleaning::find()->where(' YEAR("ditagihkan_bulan") = YEAR(str_to_date(:your_date_input1, "%m-%Y")
AND MONTH("ditagihkan_bulan") = MONTH(str_to_date(:your_date_input2, "%m-%Y") )
->bindValue(':your_date_input1', $your_date_input)
->bindValue(':your_date_input2', $your_date_input)
->all();
you can use directQuery:
Yii::$app->db->createCommand('SELECT * FROM tagihan_cleaning
WHERE YEAR("ditagihkan_bulan") = 2017 AND
MONTH("ditagihkan_bulan") = 06')
->queryAll();
With Prepared statement:
$post = Yii::$app->db->createCommand('SELECT * FROM tagihan_cleaning WHERE YEAR("ditagihkan_bulan")=:year AND MONTH("ditagihkan_bulan")=:month')
->bindValue(':year', '2017')
->bindValue(':month', '06')
->queryOne();
Related
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.
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
I'm trying to execute the following query using knex.js and MySql
SELECT
m.id,
TIME(date_created) AS `timestamp`,
u.username,
m.`message`
FROM
`messages` AS m
INNER JOIN users AS u ON u.id = m.user_id
WHERE
m.game_id IS NULL
AND m.`date_created` > DATE_SUB(
CURRENT_TIMESTAMP (),
INTERVAL 12 HOUR
)
ORDER BY
m.`date_created` ASC
LIMIT 50
For proper handling expressions in where closure such as DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 12 HOUR) according to documentation there is whereRow() method in knex.
I tried to use select() method as
select('messages.id', 'TIME(date_created) AS timestamp', 'users.username', 'messages.message')
But knex masks TIME(date_created) expression in a way it should to be a column name. Does anybody know a way to use a custom expressions in selects?
I did not found exact answer on my question but I've found a solution which allows me to move forward. I created separate model which uses standard Bookshelf(knex) export:
var Bookshelf = require('bookshelf')(knex);
module.exports.DB = Bookshelf;
And created separate method in that model where I could use DB.knex.raw() for masking DB expressions in SELECT. So I became able to write the query above in the following way:
var DB = require('./../db').DB;
var Messages = DB.Model.extend({
tableName: 'messages',
hasTimestamps: false,
idAttribute: 'id'
},
{
getMessagesHistory: function (gameId) {
return this.query().select('messages.id', DB.knex.raw('TIME(date_created) AS timestamp'), 'users.username', 'messages.message')
.innerJoin('users', 'messages.user_id', 'users.id')
.whereRaw("messages.game_id " + (gameId == 0 ? "IS NULL" : "= " + gameId))
.andWhereRaw("messages.date_created > DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 12 HOUR)")
.orderBy('messages.date_created', 'ASC')
.limit(50);
}
}
);
module.exports = Messages;
You can wrap any argument with knex.raw() to tell the framework that it's a raw piece of SQL:
select(
'messages.id',
knex.raw('TIME(date_created) AS timestamp'),
'users.username',
'messages.message',
)
See http://knexjs.org/#Raw-Bindings
I have a simple Person tree with parent_id.
I wont to build a (Yii2) query to find all children of a given Person, that are parent of someone else (a.k.a not leaves).
The output SQL should looks like this:
select * from person t
where exists (select 1 from person p2 where t.id = p2.parent_id);
But cant find the right way to build this with the query builder, there is a method ->exists(), but not much documentation/examples about it.
Not sure if i understood correctly, but do you look something like this.
$subQuery = (new \yii\db\Query)
->select([new \yii\db\Expression('1')])
->from('person p2')
->where('t.id = p2.parent_id');
$query = (new \yii\db\Query())
->select('*')
->from('person t')
->where(['exists', $subQuery]);
$command = $query->createCommand();
print_r ($command->sql);
Generates sql like:
SELECT * FROM `person` `t` WHERE EXISTS (SELECT 1 FROM `person` `p2` WHERE t.id = p2.parent_id)
You should try something like :
$tableName = Person::tableName();
$subQuery = (new Query())->select('*')->from($tableName . ' t2')->where('t1.id=t2.parent_id');
$persons = Person::find()->from($tableName . ' t1')->where(['exists', $subQuery])->all();
http://www.yiiframework.com/doc-2.0/guide-db-query-builder.html#where
I don't know the right way with only queries, but if you use PHP also, then I think this will help you.
And also try to search in Google with keywords: hierarchical menu PHP
I am trying to convert a MYSQL query to codeigniter and going no wheres real fast. I am trying to convert this query
$conn->prepare("SELECT `id`,`song`,`artist`,`album`,`track`,`mix_name`,`date` FROM `podcasts` where mix_number = (SELECT MAX(mix_number) FROM podcasts) order by track asc");
This is in my model:
//$where = '(SELECT MAX(mix_number)from podcasts)';
$this->db->select('id,song,artist,album,track,mix_name,date, link');
//$this->db->where('mix_number', '(SELECT MAX(mix_number)from podcasts)');
$this->db->order_by('track', 'asc');
$query = $this->db->get('podcasts');
return $query->result();
My problem area is in the where statement. When I comment out the where statement I get the data. Obviously not in the manner I want it.
I am doing it this way becuase my next query(s) will be
("SELECT `id`,`song`,`artist`,`album`,`track`,`mix_name`,`date` FROM `podcasts` where mix_number = **(SELECT MAX(mix_number) FROM podcasts) - 1** order by track asc")
And on down to (SELECT MAX(mix_number) FROM podcasts) - 3
Any thoughts on the proper way of writing the where statement? Thank you for yout time.
Set the third argument of where() to false to prevent CI from altering the string you pass in to the second argument, then you can do the subquery:
return $this->db
->select('id,song,artist,album,track,mix_name,date, link')
->where('mix_number', '(SELECT MAX(mix_number) from podcasts)', false)
->order_by('track', 'asc')
->get('podcasts')
->result();
https://www.codeigniter.com/userguide2/database/active_record.html$this->db->where() accepts an optional third parameter. If you set it to FALSE, CodeIgniter will not try to protect your field or table names with backticks.
For me this produces the following query:
SELECT `id`, `song`, `artist`, `album`, `track`, `mix_name`, `date`, `link`
FROM (`podcasts`)
WHERE mix_number = (SELECT MAX(mix_number) from podcasts) ORDER BY `track` asc
If you are not too particular about using CodeIgniter's Active Record syntax, you can simply use your query as is:
$sql = "SELECT `id`,`song`,`artist`,`album`,`track`,`mix_name`,`date` FROM `podcasts` where mix_number = (SELECT MAX(mix_number) FROM podcasts) order by track asc";
$this->db->query($sql);
and then use $query->result() to get your results.