Table view OR temporary table in Doctrine + symfony 2.3 - doctrine-orm

I was trying to implement bayesian average logic in doctrine and symfony.
I have basic native Mysql query like this:
Create View `ratings` AS
SELECT
restaurant_id,
(SELECT count(restaurant_id) FROM ratings) / (SELECT count(DISTINCT restaurant_id) FROM ratings) AS avg_num_votes,
(SELECT avg(rating) FROM ratings) AS avg_rating,
count(restaurant_id) as this_num_votes,
avg(rating) as this_rating
FROM
ratings
GROUP BY
restaurant_id
SELECT
restaurant_id,
((avg_num_votes * avg_rating) + (this_num_votes * this_rating)) / (avg_num_votes + this_num_votes) as real_rating
FROM `ratings`
This query creates table view from where we are retrieving records.
From some documents I came to know that we can't create view in Doctrine. So another option is to create temporary table. How we can create temp table with different structure.
Referring : http://shout.setfive.com/2013/11/21/doctrine2-using-resultsetmapping-and-mysql-temporary-tables/
// Add the field info for each column/field
foreach( $classMetadata->fieldMappings as $id => $obj ){
$rsm->addFieldResult('u', $obj["columnName"], $obj["fieldName"]);
// I want to crate new fields to store avg rating etc.
}
How we can implement this in Doctrine and Symfony?

Related

how to get latest second row in django?

can anyone help me I'm new to django so I don't know how to make sql queries into django code.
my sql table is :
select * from mangazones.mangabank_comic_banks;
the table image:
sql table image
then for second row query :
WITH added_row_number AS (SELECT comic_chapter,comic_english_name_id, row_number() OVER(PARTITION BY comic_english_name_id ORDER BY comic_chapter DESC) AS row_num FROM mangazones.mangabank_comic_banks) SELECT * FROM added_row_number WHERE row_num = 2;
I get table:
seond row table
I want second row table query in django also.
Can anyone please help me?
You can get the latest or latest 2nd value in Django model:
If you want to filter using primary key:
latest_second = Model_Name.objects.filter().order_by('-pk')[1]
If you have created date and time you can do it such way:
latest_second = Model_Name.objects.filter().order_by('-created')[1]
here, filter() is for filtering certain items.
if you don't want to filter items then you can use:
latest_second = Model_Name.objects.all().order_by('-pk')[1]

Django How to select differrnt table based on input?

I have searched for the solution to this problem for a long time, but I haven't got the appropriate method.
Basically All I have is tons of tables, and I want to query value from different tables using raw SQL.
In Django, we need a class representing a table to perform the query, for example:
Routes.objects.raw("SELECT * FROM routes")
In this way, I can only query a table, but what if I want to query different tables based on the user's input?
I'm new to Django, back in ASP.NET we can simply do the following query:
string query = "SELECT * FROM " + county + " ;";
var bus = _context.Database.SqlQuery<keelung>(query).ToList();
Is this case, I can do the query directly on the database instead of the model class, and I can select the table based on the user's selection.
Is there any method to achieve this with Django?
You can run raw queries in Django like this -
From django.db import connection
cursor = connection.cursor()
table = my_table;
cursor.execute("Select * from " + table)
data = cursor.fetchall()

Doctrine 2 way too slower than Laravel's Eloquent

I'm trying to use Doctrine 2 (LaravelDoctrine) instead of Eloquent.
Performing simple query of getting paginated data:
// Doctrine
$orders = $this->orderRepository->paginateAll(50);
// Eloquent
$orders = $this->orders->paginate(50);
I end up with Doctrine queries taking too much time (info from Laravel Debugbar):
Doctrine queries took 3.86s
1.79s
SELECT DISTINCT id_0 FROM (SELECT o0_.id AS id_0, o0_.customer_id AS customer_id_1, o0_.customer_ref AS customer_ref_2, ... FROM orders o0_) dctrn_result LIMIT 50 OFFSET 0
16.63ms
SELECT o0_.id AS id_0, o0_.customer_id AS customer_id_1, o0_.customer_ref AS customer_ref_2, ... FROM orders o0_ WHERE o0_.id IN (?)
2.05s
SELECT COUNT(*) AS dctrn_count FROM (SELECT DISTINCT id_0 FROM (SELECT o0_.id AS id_0, o0_.customer_id AS customer_id_1, o0_.customer_ref AS customer_ref_2, ... FROM orders o0_) dctrn_result) dctrn_table
Eloquent queries took 50.38ms
36.73ms
select count(*) as aggregate from `orders`
13.65ms
select * from `orders` limit 50 offset 0
I'm not pasting whole doctrine queries here as there's 65 columns in the table, but they all used with 'AS', identically to mentioned columns.
Is this is intended Doctrine 2 behavior to be so slow or am I missing something?
I used annotations as Meta Data for mapping and Doctrine\ORM\EntityRepository for accessing the data.
Thank you in advance.
Best Regards.

Doctrine join query to get all record satisfies count greater than 1

I tried with normal sql query
SELECT activity_shares.id FROM `activity_shares`
INNER JOIN (SELECT `activity_id` FROM `activity_shares`
GROUP BY `activity_id`
HAVING COUNT(`activity_id`) > 1 ) dup ON activity_shares.activity_id = dup.activity_id
Which gives me record id say 10 and 11
But same query I tried to do in Doctrine query builder,
$qb3=$this->getEntityManager()->createQueryBuilder('c')
->add('select','c.id')
->add('from','MyBundleDataBundle:ActivityShare c')
->innerJoin('c.activity', 'ca')
// ->andWhere('ca.id = c.activity')
->groupBy('ca.id')
->having('count(ca.id)>1');
Edited:
$query3=$qb3->getQuery();
$query3->getResult();
Generated SQL is:
SELECT a0_.id AS id0 FROM activity_shares a0_
INNER JOIN activities a1_ ON a0_.activity_id = a1_.id
GROUP BY a1_.id HAVING count(a1_.id) > 1
Gives only 1 record that is 10.I want to get both.I'm not getting idea where I went wrong.Any idea?
My tables structure is:
ActivityShare
+-----+---------+-----+---
| Id |activity |Share| etc...
+-----+---------+-----+----
| 1 | 1 |1 |
+-----+---------+-----+---
| 2 | 1 | 2 |
+-----+---------+-----+---
Activity is foreign key to Activity table.
I want to get Id's 1 and 2
Simplified SQL
first of all let me simplify that query so it gives the same result :
SELECT id FROM `activity_shares`
GROUP BY `id`
HAVING COUNT(`activity_id`) > 1
Docrtrine QueryBuilder
If you store the id of the activty in the table like you sql suggests:
You can use the simplified SQL to build a query:
$results =$this->getEntityManager()->createQueryBuilder('c')
->add('select','c.id')
->add('from','MyBundleDataBundle:ActivityShare c')
->groupBy('c.id')
->having('count(c.activity)>1');
->getResult();
If you are using association tables ( Doctrine logic)
here you will have to use join but the count may be tricky
Solution 1
use the associative table like an entitiy ( as i see it you only need the id)
Let's say the table name is activityshare_activity
it will have two fields activity_id and activityshare_id, if you find a way to add a new column id to that table and make it Autoincrement + Primary the rest is easy :
the new entity being called ActivityShareActivity
$results =$this->getEntityManager()->createQueryBuilder('c')
->add('select','c.activityshare_id')
->add('from','MyBundleDataBundle:ActivityShareActivity c')
->groupBy('c.activityshare_id')
->having('count(c.activity_id)>1');
->getResult();
the steps to add the new identification column to make it compatible with doctrine (you need to do this once):
add the column (INT , NOT NULL) don' t put the autoincrement yet
ALTER TABLE tableName ADD id INT NOT NULL
Populate the column using a php loop like for
Modify the column to be autoincrement
ALTER TABLE tableName MODIFY id INT NOT NULL AUTO_INCREMENT
Solution2
The correction to your query
$result=$this->getEntityManager()->createQueryBuilder()
->select('c.id')
->from('MyBundleDataBundle:ActivityShare', 'c')
->innerJoin('c.activity', 'ca')
->groupBy('c.id') //note: it's c.id not ca.id
->having('count(ca.id)>1')
->getResult();
I posted this one last because i am not 100% sure of the output of having+ count but it should word just fine :)
Thanks for your answers.I finally managed to get answer
My Doctrine query is:
$subquery=$this->getEntityManager()->createQueryBuilder('as')
->add('select','a.id')
->add('from','MyBundleDataBundle:ActivityShare as')
->innerJoin('as.activity', 'a')
->groupBy('a.id')
->having('count(a.id)>1');
$query=$this->getEntityManager()->createQueryBuilder('c')
->add('select','c.id')
->add('from','ChowzterDataBundle:ActivityShare c')
->innerJoin('c.activity', 'ca');
$query->andWhere($query->expr()->in('ca.id', $subquery->getDql()))
;
$result = $query->getQuery();
print_r($result->getResult());
And SQL looks like:
SELECT a0_.id AS id0 FROM activity_shares a0_ INNER JOIN activities a1_ ON a0_.activity_id = a1_.id WHERE a1_.id IN (SELECT a2_.id FROM activity_shares a3_ INNER JOIN activities a2_ ON a3_.activity_id = a2_.id GROUP BY a2_.id HAVING count(a2_.id) > 1

Doctrine2 DQL select on a resultset (double group by)

I have a complex query that need to be written in DQL / Doctrine2.
The pseudo query (I left out all the extra joins / calculations) is:
SELECT
a, SUM(b)
FROM (
SELECT
a, SUM(b)
FROM tbl
GROUP BY a,c
) calc
GROUP BY a
First a group by on column a and c, and a select with again a group by on a afterwards.
The (pseudo) code on the select part is easy in querybuilder:
$queryBuilder = $this->entityManager->createQueryBuilder();
$queryBuilder
->select(array('tbl'))
->addSelect('SUM(tbl.b)')
->from('\Model\MyModel', 'tbl')
->groupBy('a')
->addGroupBy('c');
$query = $queryBuilder->getQuery();
$results = $query->getResult();
However, how do I query this result again?
Is this possible?
Or can I somehow put them togheter in 1 queryBuilder object?