Doctrine 2 DQL CASE WHEN in Count - mysql

I have this Query in native MySQL Code
SELECT *
FROM `turn`
LEFT JOIN (
poi
) ON ( turn.id = poi.turn_id )
GROUP BY turn.id
ORDER BY count( case when poi.image = 1 then 1 else null end) DESC;
I need to rebuild this in Doctrine 2 DQL
My attempt so far is this:
SELECT t, COUNT((CASE WHEN Bundle\Entity\Poi p.image = 1 then 1 ELSE NULL END)) AS num
FROM Bundle\Entity\Turn t
JOIN t.pois p
GROUP BY t.id
ORDER BY num DESC
And im getting this error:
An exception has been thrown during the rendering of a template ("[Syntax Error] line 0, col 99: Error: Expected end of string, got '.'") in Bundle:Admin:showTurnsFiltered.html.twig at line 75.
What am i doing wrong?

I found it by myself after hours of trying and searching, it's working with this DQL:
$dql = 'SELECT t,
SUM(CASE WHEN p.image = 1 THEN 1 ELSE 0 END) AS numImage
FROM Bundle\Entity\Turn t
JOIN t.pois p
GROUP BY t.id
ORDER BY numImage DESC';
Important that you need to use SUM instead of COUNT

You need to use ResultSetMappingBuilder. It would look something like :
public function getTurn()
{
$rsm = new ResultSetMappingBuilder($this->_em);
$rsm->addRootEntityFromClassMetadata('Foo\BarBundle\Entity\Turn', 't');
$rsm->addJoinedEntityFromClassMetadata('Foo\BarBundle\Entity\Poi', 'p', 't', 'poi', array('id' => 'poi_id'));
$rsm->addScalarResult('ImageCount', 'ImageCount');
$sql = 'SELECT t.id, t.foo, t.bar,
SUM(CASE WHEN p.image = 1 then 1 else null end) ImageCount,
FROM Turn t
INNER JOIN poi p ON t.id = p.turn_id
ORDER BY ImageCount DESC';
$query = $this->_em->createNativeQuery($sql, $rsm);
return $query->getScalarResult();
}
note: you might need to change $query->getScalarResult()to $query->getResult().

Related

Output of 3 queries

Got this 3 in 1 query:
SELECT * FROM
(
SELECT mesures.date j, AVG(mesures.valeur) maxi
FROM mesures
JOIN plages_horaire ON mesures.id_plage = plages_horaire.id_plage
WHERE MONTH(mesures.date) = '9' AND YEAR(mesures.date) = '2016' AND mesures.code_station = 'P02SE' AND mesures.id_crit = '1' AND mesures.id_type = '1'
GROUP BY mesures.date
) maxi
,
(
SELECT AVG(mesures.valeur) mini
FROM mesures
JOIN plages_horaire ON mesures.id_plage = plages_horaire.id_plage
WHERE MONTH(mesures.date) = '9' AND YEAR(mesures.date) = '2016' AND mesures.code_station = 'P02SE' AND mesures.id_crit = '1' AND mesures.id_type = '2'
GROUP BY mesures.date
) mini
,
(
SELECT AVG(mesures.valeur) moy
FROM mesures
JOIN plages_horaire ON mesures.id_plage = plages_horaire.id_plage
WHERE MONTH(mesures.date) = '9' AND YEAR(mesures.date) = '2016' AND mesures.code_station = 'P02SE' AND mesures.id_crit = '1' AND mesures.id_type = '3'
GROUP BY mesures.date
) moy
GROUP BY j
Problem is that I get what I want excepting values of the 2 last columns are the same at every rows:
query output
I believe it's because of the GROUP BY.
From what I can see from your query, you don't need the plage_horaire table. You can also simplify the logic greatly by using conditional aggregation:
SELECT m.date,
AVG(CASE WHEN m.id_type = 1 THEN m.valeur END) maxi,
AVG(CASE WHEN m.id_type = 2 THEN m.valeur END) mini,
AVG(CASE WHEN m.id_type = 3 THEN m.valeur END) maxmoy,
FROM mesures m
WHERE MONTH(m.date) = 9 AND YEAR(m.date) = 2016 AND
m.code_station = 'P02SE' AND m.id_crit = 1 AND m.id_type IN (1, 2, 3)
GROUP BY m.date ;
Notice that I also removed the quotes from the numeric constants. MONTH() and YEAR() return numbers, so quotes are not appropriate. I am guessing that the ids are numeric as well.

Case condition is not working

What I need:
I need to check if eventvisitor.published is 1 then increment by zero else eventvisitor is equal to 0.
mysql query
SUM(
CASE
WHEN eventvisitor.published =1
THEN eventvisitor.published=eventvisitor.published+0
ELSE eventvisitor.published=0
END
) AS eventvsisitorpublished
sql query works
$qb->select('
eve.id,
SUBSTRING(ed.value,1,150) des,
eve.membership,
eve.name,
eve.abbrName abbr_name,
eve.membership paid,
eve.wrapper event_wrapper,
(case when attach.cdnUrl is null then attach.value else attach.cdnUrl end) event_samll_wrapper,
eve.url event_url,
eve.website,
eve.eventType,
venue.name venue_name,
e.startDate,
e.endDate,
ct.name city,
c.name country,
c.url country_url,
c.shortname country_shortname,
category.id industry_id,
category.name industry_name,
category.url industry_url,
eve.status event_status,
count(distinct eventvisitor.user) PeopleAttending
')
->add('from', $from);
->innerJoin('Entities\City','ct','with','eve.city = ct.id')
->innerJoin('Entities\Country','c','with','eve.country = c.id')
->innerJoin('Entities\EventEdition','e','with','eve.eventEdition = e.id')
->innerjoin('Entities\EventCategory','cat','with','e.event = cat.event')
->innerjoin('Entities\Category','category','with','cat.category = category.id')
->leftJoin('Entities\Venue','venue','with','e.venue=venue.id')
->leftJoin('Entities\EventVisitor','eventvisitor','with','eve.id=eventvisitor.event')
//->leftJoin('Entities\Venue','v','with','v.id = e.venue')
->leftJoin('Entities\EventData','ed','with','eve.eventEdition = ed.eventEdition')
->leftJoin('Entities\Attachment','attach','with','eve.wrapperSmall = attach.id')
->Where("ed.title ='desc' or ed.title is null")
->andWhere("eve.id in (".$res.")")
->andWhere("eventvisitor.published =1")
works check in where condition.
problem I'm facing: I'm getting 500 internal error
where I have done wrong any suggestion are most welcome.
use this
SUM(
IF(eventvisitor.published ==1, eventvisitor.published , 0)
) AS eventvsisitorpublished

Is it possible to change the order by "DESC/ASC" in a case statment - MySql

I have a select statement with a order by command. Now the order by command has a case statment based on the status of the record it sort by a different column. However, I need to also the order by DESC if the status = 1 else order by ASC.
How can I do this?
This is my current statement:
SELECT ph.phone_call_id AS id, ph.call_subject AS callSubject,
ph.trigger_on AS triggerOn,
ph.isAppointment,
IFNULL(ph.last_attempt_on, "") last_attempt_on,
ind.name AS industry,
ac.account_id,
ac.account_name AS accountName
FROM phone_calls AS ph
INNER JOIN accounts AS ac ON ph.account_id = ac.account_id
INNER JOIN industries AS ind ON ind.industry_id = ac.industry_id
INNER JOIN call_codes AS cc ON ph.call_code_id = cc.call_code_id
WHERE ac.status = 1
AND ph.status = '.$call_status.'
AND ph.owner_id = '. USER_ID .'
AND ac.do_not_call = 0
ORDER BY CASE WHEN ph.status = 1 THEN ph.trigger_on ELSE ph.last_attempt_on END
Is this what you want?
ORDER BY (CASE WHEN ph.status = 1 THEN ph.trigger_on end) DESC,
(case when ph.status <> 1 then ph.last_attempt_on END) ASC

MySQL select subqueries

This is what I have at the moment.
$db =& JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('`#__catalog_commit`.`id` as id, `#__catalog_commit`.`date` as date, COUNT(`#__catalog_commit_message`.`commit_id`) as count,
(SELECT COUNT(`#__catalog_commit_message`.`type`) as count_notice FROM `#__catalog_commit_message` WHERE `#__catalog_commit_message`.`type` = 1 GROUP BY `#__catalog_commit_message`.`type`) as count_notice,
(SELECT COUNT(`#__catalog_commit_message`.`type`) as count_warning FROM `#__catalog_commit_message` WHERE `#__catalog_commit_message`.`type` = 2 GROUP BY `#__catalog_commit_message`.`type`) as count_warning,
(SELECT COUNT(`#__catalog_commit_message`.`type`) as count_error FROM `#__catalog_commit_message` WHERE `#__catalog_commit_message`.`type` = 3 GROUP BY `#__catalog_commit_message`.`type`) as count_error');
$query->from('#__catalog_commit_message');
$query->leftjoin('`#__catalog_commit` ON `#__catalog_commit`.`id` = `#__catalog_commit_message`.`commit_id`');
$query->group('`#__catalog_commit_message`.`commit_id`');
$query->order('`#__catalog_commit`.`id` DESC');
What I have is 2 tables with the following structures:
catalog_commit
==============
id
date
catalog_commit_message
======================
id
commit_id
type
message
Basically I want to have the count of each different types of messages per group items. In what I have it actually select every rows (Which is normal) but I'm looking for a way (nicier if possible) to have the count per messages type within the query.
EDIT: Just wanted to add that it's a JModelList.
From what I gather, this should be your query:
SELECT c.id
,c.date
,count(cm.commit_id) as ct_total
,sum(CASE WHEN cm.type = 1 THEN 1 ELSE 0 END) AS count_notice
,sum(CASE WHEN cm.type = 2 THEN 1 ELSE 0 END) AS count_warning
,sum(CASE WHEN cm.type = 3 THEN 1 ELSE 0 END) AS count_error
FROM catalog_commit c
LEFT JOIN catalog_commit_message cm ON cm.commit_id = c.id
GROUP BY c.id, c.date
ORDER BY c.id DESC
You had the order of your tables reversed in the LEFT JOIN. Also, you had weird subqueries in the SELECT list.

SQL ORDER BY query

I want to have my table,rcarddet, ordered by "SDNO" (not primary key) in ascending order with the exception of "0". So it should turn out to be like:
1
1
2
.
.
10
0
0
My query now is:
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
AND `SDNO` != 0
ORDER BY `rcarddet`.`SDNO` ASC;
The easiest way
SELECT * FROM rcarddet
WHERE RDATE = '2011-05-25' and RCNO = '1'and PLACE = 'H'
ORDER BY CASE
WHEN rcarddet.SDNO = 0 THEN [max_number_for_the_type_of_SDNO]
ELSE rcarddet.SDNO
END ASC
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
ORDER BY
`SDNO` = 0,
`SDNO`;