Converting MYSQL to Codeigniter - mysql

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.

Related

Convert Sql query to sql CodeIgniter

convert sql query to sql codeigniter
i done try to use this method
How to convert sql query to codeigniter active records
but not working for me...
so i try to post in here
this my sql query
$sql = "SELECT b.id, b.us_id, b.kredit, b.info,u.us_name,
u.us_username, u.us_email, u.us_phone, b.cnt, b.amnt
FROM users u JOIN
(SELECT id, us_id, kredit, info, COUNT(info) cnt, SUM(kredit) amnt
FROM balance_history
GROUP BY info HAVING cnt > 1
) AS b
ON u.us_id = b.us_id
WHERE b.kredit != '0' AND
b.info NOT LIKE '[PERBAIKAN]%' AND
(b.info LIKE 'Transfer saldo%' OR b.info LIKE 'Ket%')
ORDER BY b.id ASC";
thanks before...
If you aren't loaded database globally, you can load it by calling $this->load->database(); The following query may provide the same db call.
$this->db->select('id, us_id, kredit, info, COUNT(info) cnt, SUM(kredit) amnt')
->from('balance_history')
->group_by('info')
->having('cnt > 1');
$subquery = $this->db->get_compiled_select();
$query = $this->db
->select('b.id, b.us_id, b.kredit, b.info,u.us_name,u.us_username, u.us_email, u.us_phone, b.cnt, b.amnt')
->from('users u')
->join('('.$subquery.') b','u.us_id = b.us_id')
->where('b.kredit !=','0', true)
->not_like('b.info', '[PERBAIKAN]', 'after', false, true)
->where('(b.info LIKE "Transfer saldo%" OR b.info LIKE "Ket%")')
->get();

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

how to translate a very long mysql query with select and join to zend framework 1.11 model

I have this mysql query:
SELECT
freeAnswers.*,
(SELECT `districtCode`
FROM `geodatas`
WHERE `zipCode` = clients.zipCode
GROUP BY `zipCode`
LIMIT 0, 1) as districtCode,
clients.zipCode,
clients.gender,
clients.startAge,
clients.endAge,
clients.mail,
clients.facebook,
surveys.customerId,
surveys.activityId,
surveys.name as surveyName,
customers.companyName,
activities.name as activityName
FROM freeAnswers,
clients,
surveys,
customers,
activities
WHERE freeAnswers.surveyId = surveys.id
AND surveys.customerId = customers.id
AND activities.id = surveys.activityId
AND clients.id = freeAnswers.clientId
AND customers.id = 1
ORDER BY activityName asc
LIMIT 0, 10
the query is correct on my mysql server but when I try to use it in Zend Framework 1.11 model
I get this error: Mysqli prepare error: Operand should contain 1 column(s)
Please, could anyone help me to make it run well?
Best Regards,
Elaidon
Here is some code that should work. Zend_Db_Select doesn't really provide a way to select from multiple tables in the FROM clause without using a JOIN so this feels a bit hackish to me in regards to one small part of the query. Your best bet will probably be to rewrite the query using JOINs where appropriate.
$subselect = $db->select()
->from('geodatas', 'districtCode')
->where('zipCode = clients.zipCode')
->group('zipCode')
->limit(1, 0);
$from = $db->quoteIdentifier('freeAnswers') . ', ' .
$db->quoteIdentifier('clients') . ', ' .
$db->quoteIdentifier('surveys') . ', ' .
$db->quoteIdentifier('customers') . ', ' .
$db->quoteIdentifier('activities');
$select = $db->select()
->from(array('activities' => new Zend_Db_Expr($from)),
array('freeanswers.*',
'districtCode' =>
new Zend_Db_Expr('(' . $subselect . ')'),
'clients.zipCode', 'clients.gender', 'clients.startAge',
'clients.endAge', 'clients.mail', 'clients.facebook',
'clients.customerId', 'clients.activityId',
'surveyName' => 'surveys.name', 'customers.companyName',
'activityName' => 'activities.name'))
->where('freeAnswers.surveyId = surveys.id')
->where('surveys.customerId = customers.id')
->where('activities.id = surveys.activityId')
->where('clients.id = freeAnswers.clientId')
->where('customers.id = ?', 1)
->order('activityName ASC')
->limit(10, 0);
The only reason I say it is hackish is because of the line:
->from(array('activities' => new Zend_Db_Expr($from)),
Since from() really only works with one table, I create a Zend_Db_Expr and specify the correlation as the last table name in the expression. If you don't pass a Zend_Db_Expr, it will either quote your comma separated table name incorrectly, or if you pass an array of table names, it just uses the first. When you pass a Zend_Db_Expr with no name, it defaults to use AS t which also doesn't work in your case. That is why I put it as is.
That returns the exact SQL you provided except for the last thing mentioned. Here is actually what it returns:
SELECT
`freeanswers`.*,
(SELECT `geodatas`.`districtCode`
FROM `geodatas`
WHERE (zipCode = clients.zipCode)
GROUP BY `zipCode`
LIMIT 1) AS `districtCode`,
`clients`.`zipCode`,
`clients`.`gender`,
`clients`.`startAge`,
`clients`.`endAge`,
`clients`.`mail`,
`clients`.`facebook`,
`clients`.`customerId`,
`clients`.`activityId`,
`surveys`.`name` AS `surveyName`,
`customers`.`companyName`,
`activities`.`name` AS `activityName`
FROM `freeAnswers`,
`clients`,
`surveys`,
`customers`,
`activities` AS `activities`
WHERE (freeAnswers.surveyId = surveys.id)
AND (surveys.customerId = customers.id)
AND (activities.id = surveys.activityId)
AND (clients.id = freeAnswers.clientId)
AND (customers.id = 1)
ORDER BY `activityName` ASC
LIMIT 10
So that will work but eventually you will want to rewrite it using JOIN instead of specifying most of the WHERE clauses.
When dealing with subqueries and Zend_Db_Select, I find it easy to write each subquery as their own queries before writing the final query, and just insert the subqueries where they need to go and Zend_Db handles the rest.
Hope that helps.

Can you check to see if there will be any results

I'm displaying Spotlight post on search page.
When a user enters a keyword to search for a post I like to bring a Spotlight post using that keyword. If there is no post with that keyword then I would want to just bring any Spotlight post from database.
My questions is, can I check this in a MySQL query to see if they will be any results with this keyword, if not then ignore this keyword?
My query
SELECT id, title, desc
FROM post
WHERE isActive = 1
AND title = 'keyword'
but if I'm getting 0 results with this query I would like to ignore this and run this instead
SELECT id, title, desc
FROM post
WHERE isActive = 1
desc is MySQL's reserved keyword (used for ordering results in a *desc*ending order). To use it as a column name, you need to put it in backticks
$select = " SELECT id, title, `desc` ";
$from = ' FROM post';
$where = 'WHERE isActive=1 and title="%$keywords%"';
$sql = $select.$from.$where;
This is what I have done to solve my problem.
$select = " SELECT id, title, desc ";
$from = ' FROM post';
$where = 'WHERE isActive=1 and title="%$keywords%"';
$sql = $select.$from.$where;
if no result then overwrite
$where = 'WHERE isActive=1';
$sql = $select.$from.$where;
If anyone know anyother way please let me know.

Simplify sql query to obtain one line per id

I have a multi-table SQL query.
My need is: The query should I generate a single line by 'etablissement_id' ... and all information that I want to be back in the same query.
The problem is that this query is currently on a table where "establishment" may have "multiple photos" and suddenly, my query I currently generates several lines for the same id...
I want the following statement - LEFT JOINetablissementContenuMultimediaON etablissement.etablissement_id = etablissementContenuMultimedia.etablissementContenuMultimedia_etablissementId - only a single multimedia content is displayed. Is it possible to do this in the query below?
Here is the generated query.
SELECT DISTINCT `etablissement`. * , `etablissementContenuMultimedia`. * , `misEnAvant`. * , `quartier`. *
FROM `etablissement`
LEFT JOIN `etablissementContenuMultimedia` ON etablissement.etablissement_id = etablissementContenuMultimedia.etablissementContenuMultimedia_etablissementId
LEFT JOIN `misEnAvant` ON misEnAvant.misEnAvant_etablissementId = etablissement.etablissement_id
LEFT JOIN `quartier` ON quartier_id = etablissement_quartierId
WHERE (
misEnAvant_typeMisEnAvantId =1
AND (
misEnAvant_dateDebut <= CURRENT_DATE
AND CURRENT_DATE <= misEnAvant_dateFin
)
)
AND (
etablissement_isActive =1
)
ORDER BY `etablissement`.`etablissement_id` ASC
LIMIT 0 , 30
Here is the code used ZF
public function find (){
$db = Zend_Db_Table::getDefaultAdapter();
$oSelect = $db->select();
$oSelect->distinct()
->from('etablissement')
->joinLeft('etablissementContenuMultimedia', 'etablissement.etablissement_id = etablissementContenuMultimedia.etablissementContenuMultimedia_etablissementId')
->joinLeft('misEnAvant', 'misEnAvant.misEnAvant_etablissementId = etablissement.etablissement_id')
->joinLeft('quartier', 'quartier_id = etablissement_quartierId ')
->where ('misEnAvant_typeMisEnAvantId = 1 AND (misEnAvant_dateDebut <= CURRENT_DATE AND CURRENT_DATE <= misEnAvant_dateFin) ')
->where ('etablissement_isActive = 1')
->order(new Zend_Db_Expr('RAND()'));
$zSql = $oSelect->__toString();
if(isset($_GET['debug']) AND $_GET['debug'] == 1)
echo $zSql ;
//die();
$oResultEtablissement = $db->fetchAll($oSelect);
return $oResultEtablissement ;
}
Can you help me?
Sincerely,
If you are looking to have only one of the media displayed out of many regardless of which it may be then you can just add a limit to the query? After that you can tweak the query for ASCending or DESCending perhaps?
Is this query supposed to have images (or image as it were) for one establishment, or one image each for each active establishment? I see you have a limit 0,30 which means you're likely paginating....
If the result you want is a search for only one establishment, and the first image it comes to would work fine .. just use "limit 1" and you'll only get one result.
I took the time to redo the whole model of the database ... and now it works. There was no solution for a system as flawed