I use symfony 1.4 and I want to group some data, order it by grouped columns then select the one who has the most records.
My code looks like this:
$c = new Criteria();
$c->addGroupByColumn(MetricPeer::POST_TYPE_ID);
$c->addDescendingOrderByColumn(MetricPeer::POST_TYPE_ID);
$posts = MetricPeer::doSelectOne($c);
I know that line "$c->addDescendingOrderByColumn(MetricPeer::POST_TYPE_ID);" it is ordering data just by the numbers and it is not correct.
public static function topPosts($limit,$source_id,$interval1,$interval2,$con = null) {
if($con === null) $con = Propel::getConnection(self::DATABASE_NAME);
$sql = "SELECT *, COUNT(post_id) AS value_occurrence FROM metric WHERE source_id LIKE ".$source_id." AND visit_out BETWEEN '".$interval1."' AND '".$interval2."' GROUP BY post_id ORDER BY value_occurrence DESC LIMIT ".$limit."";
$stmt = $con->prepare($sql);
$stmt->execute();
$topreads = MetricPeer::populateObjects($stmt);
return $topreads;
}
This is my humble solution for now, I thought it might be useful for others, too.
Thank you.
Related
Retrieve a node based on condition:
$query = \Drupal::entityQuery('node')
->condition('type', 'my_content_type')
->condition('title', 'my node title');
$nid = $query->execute();
The result of $nid is the correct node ID but the format is a string, (es: "123")
When I want to load the node by its ID, I write:
$node_id = Node::load($nid);
Doing this, the result I get is NULL because the variable $nid is holding a string (not integer).
If I write the code like this:
$node_id = Node::load(123);
I get the node loaded.
How can I convert the variable string ($nid) as an integer ?
I tried:
$nid_int = (int) $nid;
$node_id = Node::load($nid_int);
also I tried:
$nid_int = intval($nid);
$node_id = Node::load($nid_int);
But I alwas get result NULL
Thanks for your help
You can't use Node::load($nid); directly, because the $query->execute() return an array like ['vid' => "nid"].
$query = \Drupal::entityQuery('node')
->condition('type', 'my_content_type')
->condition('title', 'my node title');
$nids = $query->execute();
$nid = (int)array_shift($nids);
Can try:-
$nid_string = $nid->__toString();
$node_id = Node::load((int) $nid_string);
I realized this sql which works without problems
SELECT meeting.name, meeting.date, community.name, participation.isPresent, participation.user_id
FROM meeting
INNER JOIN community
ON meeting.community_id = community.id
AND community.is_active = 1
LEFT join participation
ON meeting.id = participation.meeting_id
AND participation.user_id = 1078
WHERE meeting.date >= CURRENT_DATE()
ORDER BY meeting.date DESC
I'm trying to reproduce it with the doctrine query builder but I never got the right result. The user id part doesn't seem to be part of the leftJoin function but is applied to the request globally, which is not what I want.
public function getNextMeetings()
{
$qb = $this->createQueryBuilder('m')
->select('m.name AS meeting, m.date, c.name AS community, p.isPresent', 'IDENTITY(p.user) AS user')
->innerJoin('m.community', 'c')
->where('c.isActive = true')
->leftJoin('m.participations', 'p')
//->leftJoin('p.user', 'u')
//->where('u.id = 1078 OR u.id IS NULL')
//->where('IDENTITY(p.user) = 1078')
->andWhere('m.date >= CURRENT_DATE()')
->orderBy('m.date', 'DESC');
return $qb->getQuery()->execute();
}
My comments are what I tried to fix this issue.
Check Working with QueryBuilder: High level API methods
More precisely, the definition od leftJoin() function:
public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null);
You can place a condition on the joined Entity by:
use Doctrine\ORM\Query\Expr;
->leftJoin('m.participations', 'p', Expr\Join::WITH, 'p.user = :userId')
->setParameter('userId', 1078)
Note you do not need a condition for "meeting.id = participation.meeting_id", as this is autoapplied by the relation m.participations to the join constructed.
I want to produce a DQL for following MySQL query:
SELECT * FROM `folders` AS `t` WHERE `t`.`Library` = #myLib AND AND `t`.`Id` NOT IN (
SELECT DISTINCT(`f`.`Id`) FROM `folders` AS `f` JOIN `folders` AS `ff` ON (`f`.`Position` LIKE CONCAT(`ff`.`Position`, '%')) WHERE `ff`.`Active` = 1 AND `ff`.`Library` = #myLib AND `f`.`Library` = #myLib
)
ORDER BY `t`.`Position` ASC
The query works fine in mySQL and returns correct records.
To generate DQL I've tried both below options:
1.
$query = $em->createQuery("SELECT F FROM MyBundle:Folders T WHERE T.Library = :libid AND T.id NOT IN (
SELECT DISTINCT(F.id) FROM MyBundle:Folders F JOIN MyBundle:Folders FF WITH F.Position LIKE CONCAT(FF.Position, '%') AND F.Library = :libid AND FF.Library = :libid AND FF.Active = true
) ORDER BY T.Position ASC")
->setParameter('libid', $library);
$result = $query->getResult();
2.
$q1 = $this->createQueryBuilder('F')
->select('DISTINCT(F.id)');
$q1->join('\MyBundle\Entity\Folders', 'FF', 'WITH', $q1->expr()->like('F.Position', $q1->expr()->literal('CONCAT(FF.Position, \'%\')')))
->where('FF.Active = true')
->andWhere("FF.Library = '$library'")
->andWhere("F.Library = '$library'");
$q2 = $this->createQueryBuilder('T');
$q2->where('T.Library = :libid')
->andWhere($q2->expr()->notIn('T.id', $q1->getDQL()))
->setParameter('libid', $library)
->orderBy('T.Position', 'ASC');
$result = $q2->getQuery()->getResult();
In my perspective it seems OK but I don't know why in both ways it produce following exception:
ContextErrorException: Warning: Illegal offset type in
/var/www/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php line 601
Any help will be appreciated.
It seems no one has an answer for this. I found a temporary solution as below (I call it temporary because I'm changing my unique query to two separate queries and it seems the issue is in core of doctrine).
$qb = $this->createQueryBuilder('F')
->select('DISTINCT(F.id)');
$qb->join('\MyBundle\Entity\Folders', 'FF', 'WITH', 'F.Position LIKE CONCAT(FF.Position, \'%\')')
->where('FF.Active = true')
->andWhere("FF.Library = :library")
->andWhere("F.Library = :library")
->setParameter('library', $library);
$included_folders = $qb->getQuery()->getArrayResult();
$query = $this->createQueryBuilder('F')
->where('F.Active = false')
->andWhere('F.Library = :library')
->setParameter('library', $library)
->orderBy('F.Position', 'ASC');
if (!empty($included_folders)) {
if (count($included_folders) > 1)
{
foreach ($included_folders as $index => $value)
{
if (is_array($value))
{
$included_folders[$index] = !empty($value['id']) ? $value['id'] : $value[1];
}
}
$query->andWhere($query->expr()->notIn('F.id', $included_folders));
}
else {
$query->andWhere('F.id != :folder ')
->setParameter('folder', $included_folders[0]);
}
}
$result = $query->getQuery()->getResult();
As you see instead of getting the dql from my first query and putting it inside my second dql in notIn section which will lead to the warning message, I execute the first query and get the results then put the results inside notIn if amount of returned values are more than one, otherwise it should be in regular !=. This solved my problem for now, but as you see amount of transactions are now increased
If anyone has a better solution or any fix for the warning I will be thankful.
I've encountered the same error and it seems that this has been fixed in latest trunk of Doctrine/ORM.
Using "2.5.*#dev" as version in your composer.json for doctrine/orm should fix this bug and will let you do what you want in a single query.
I am applying this query for below D6 query , not working ..dont know wat wrong i'm doing ....does innerjoin fails in some condition
$result = db_select('px_slides','s')
->join('node','n','s.vid = n.vid')
->fields('s',array('tissue_type','body_site'))
->fields('n',array('sticky','title'))
->condition('n.status','1','=')
->condition('s.cid','126','=')
->execute()->fetchObject();
drupal 6 query i have:
$result = db_query('
SELECT n.nid, n.vid, n.sticky, n.title, n.created, s.cid, s.ref_id, s.viewurl, s.specimen_type, s.tissue_type, s.body_site, s.test_type, s.algorithm, s.result
FROM {px_slides} s INNER JOIN {node} n ON n.vid = s.vid
WHERE n.status = 1 ')->execute();
You need to put your call to ->join() on a separate line altogether, as it doesn't return the query object:
$query = db_select('px_slides','s')
->fields('s',array('tissue_type','body_site'))
->fields('n',array('sticky','title'))
->condition('n.status','1','=')
->condition('s.cid','126','=');
$query->join('node','n','s.vid = n.vid');
$result = $query->execute()->fetchObject();
The join method does not chain like that. You will have to do something like:
$query = db_select('px_slides','s')
->join('node','n','s.vid = n.vid');
$query->fields('s',array('tissue_type','body_site'))
->fields('n',array('sticky','title'))
->condition('n.status','1','=')
->condition('s.cid','126','=');
$result = $query->execute()->fetchObject();
Also you can use the to string magic method to see the query it is going to execute.
$query->__toString();
Try this...
$query = db_select('px_slides', 's');
$query->innerJoin('node,'n','s.vid = n.vid');
$query->fields('s',array('tissue_type','body_site'));
$query->fields('n',array('sticky','title'));
$query->condition('n.status','1');
$query->condition('s.cid','126');
$result= $query->execute()->fetchAll(PDO::FETCH_ASSOC);
I have been working on sorting Arraycollection like ascending , descending the numeric list. Total length of my collection will go up to 100. Now I want to preform sort to nested data like this
Data Structure
Name : String
Categories : Array ["A","x or y or z","C"]
Categories array will have maximum 3 items , out of that three items the second item can have 3 different values either X or Y or Z. My result data looks like here
{"Mike" , ["A","x","C"]}
{"Tim" , ["A","y","C"]}
{"Bob" , ["A","x","C"]}
{"Mark" , ["A","z","C"]}
{"Peter" , ["A","z","C"]}
{"Sam" , ["A","y","C"]}
anyone please explain how to sort this type of data in a way showing all "x" first , "y" next and "z" at the last and vice a versa. Any help is really appreciated. Thanks Anandh. .
You can specify a compare function in your SortField like this:
var sortfield:SortField = new SortField("Categories");
sortfield.compareFunction = myCompare;
var sort:Sort = new Sort();
sort.fields = [sortfield];
yourCollection.sort = sort;
and your compare function:
function myCompare(a:Object, b:Object):int {
/*
return -1, if a before b
return 1, if b before a
return 0, otherwise
*/
}
or something like that.. and it's untested code :)
I have created a new property to the data structure called categoryOrder In the setter I did the following and Am using the categoryOrder for sorting - sortBy = categoryOrder;. I understand little hard coding is needed but still I believe this will reduce the number of comparisons when I use compareFunction. Anyone please valid this idea. Thanks!
public function set categories(data:ArrayCollection) :void
{
if(data != null)
{
_categories = data;
for each(var categorie:Object in data)
{
switch(categorie.categoryName)
{
case "x":{categoryOrder = 1;break;}
case "y":{categoryOrder = 2;break;}
case "z":{categoryOrder = 3;break;}
}
}
}
}
Data Structure
Name : String
Categories : Array ["A","x or y or z","C"]
categoryOrder : Number