Zend Framework 2 - sql subquery - mysql

I'm trying to run a special SQL query in ZF 2.
SELECT listingId, COUNT(*) as num
FROM
(SELECT DISTINCT listingId, locationId
FROM l_f_locations
WHERE locationId IN ( 7, 9, 10)) AS foo
GROUP by listingId, HAVING num = 3
I tried creating the subquery first as it's a complete MySQL query but then fail to integrate it into the main query at all. I can't alias the subquery e.g. "AS foo" as this is a requirement for the complete SQL squery to work.
Any ideas?

First of all, you can do this without a sub-query:
SELECT listingId, COUNT(DISTINCT locationId) AS num
FROM l_f_locations
WHERE listingId IN(7,9,10)
GROUP BY listingId
HAVING num = 3;
For future reference, however, you could do the query you mention using a pair of Zend_Db_Select objects, one for the sub-query and another for the main:
$subQuery = $dbAdapter->select()
->from('l_f_locations', array('listingId', 'locationId'))
->where('locationId IN(7,9,10)')
->group('listingId')
->group('locationId');
$select = $dbAdapter->select()
->from($subQuery, array('*', 'num' => 'COUNT(*)'))
->group('listingId')
->having('num = 3');
$result = $select->query()->fetchAll();

Related

Doctrine oridinal number with mysql (Error: Expected Literal, got '#')

I need to have an oridinal number from mysql database. I found how emulate of row_num in mysql like this:
SET #row=0;
SELECT * FROM (
SELECT (#row:=#row+1) AS no, id, name FROM `attribute` ORDER BY id
) t WHERE name LIKE "%Jo%"
I begin code with:
$this->getEntityManager()->getConnection()->exec("SET #counter = 0");
and I tried:
$this->result = $this->createQueryBuilder('a')
->select('a')
->where($expr->in('att.ordinal_number', $this->createQueryBuilder('att')->
select('(#counter:=#counter+1) AS ordinal_number')->
from(\App\Entity\Attribute::class, 'att')->
orderBy('att.id')->getDQL()))
and I tried:
$this->result = $this->createQueryBuilder('a')
->select('a')
->addSelect('(SELECT (#counter:=#counter+1) AS oridinal_number, id, '
.' name FROM App:Entity:Atrribute ORDER BY id)')
Above give me:
Error: Expected Literal, got '#'
Anybody know how to emulate row_number in doctrine with mysql?
Thanks in advance.
AFAIK there is no direct way to incorporate these DB variables in DQL or query builder, you will need to execute Native SQL and then use ResultSetMapping class to map the result of query to your entity
SQL
SELECT *
FROM (
SELECT (#row:=#row+1) AS no,
id,
name
FROM `attribute` ,(SELECT #row:=0) t
ORDER BY id
) t WHERE name LIKE "%Jo%"
Resultset Mapping
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Attribute', 'a');
$rsm->addFieldResult('a', 'id', 'id');
$rsm->addFieldResult('a', 'name', 'name');
$rsm->addScalarResult('no', 'no');
$query = $this->_em->createNativeQuery('SELECT *
FROM (
SELECT (#row:=#row+1) AS no,
id,
name
FROM attribute ,(SELECT #row:=0) t
ORDER BY id
) t WHERE name LIKE ?',$rsm);
$query->setParameter(1, '%Jo%');
$users = $query->getResult();

How to run concurring SQL query?

I am trying to run this sql query.
SELECT * FROM AverageFeedInfo WHERE No = (
SELECT No FROM UserResponse2 where Not Complain = '' )
When I run SELECT No FROM UserResponse2 where Not Complain = '' individually I have result 2 and 6, but if I run this
SELECT * FROM AverageFeedInfo WHERE No = (
SELECT No FROM UserResponse2 where Not Complain = '' )
I have only the result for 2 not for 6. Is it possible to get the answer for both 2 and 6. To be more clear is it possible to run the sql query like
SELECT * FROM AverageFeedInfo WHERE No = 2 or No = 6
Generally, when checking set membership in a SQL-based context use of an IN operator is more appropriate than =.

MySql Insert Dynamic Query with Nested Select

I'm trying a MySQL Insert Query with mix of static & Dynamic Values. The INSERT command is.
INSERT INTO ebdb.requestaction(RequestID,
ActionID,
TransactionID,
IsActive,
IsComplete)
VALUES (
1,
**Dynamic Value from Below Query,
Dynamic Value from Below Query,**
1,
0);
The Query to fetch the field 2 & 3 come from the below Query.
SELECT transitionaction.TransitionID, transitionaction.ActionID
FROM transitionaction
INNER JOIN transition
ON transitionaction.TransitionID = transition.TransitionID
WHERE transition.TenantID = 1
AND transition.ProcessID = 1
AND transition.CurrentStateID = 1
ORDER BY transitionaction.TransitionID;
I'm doing something wrong in here.
Please guide me as to how this can be achieved in the most optimized way.
You can select static values as part of a query, e.g.:
INSERT INTO ebdb.requestaction(RequestID, ActionID, TransactionID, IsActive, IsComplete)
SELECT 1, transitionaction.ActionID, transitionaction.TransitionID, 1, 0
FROM transitionaction
INNER JOIN transition
ON transitionaction.TransitionID = transition.TransitionID
WHERE transition.TenantID = 1
AND transition.ProcessID = 1
AND transition.CurrentStateID = 1
ORDER BY transitionaction.TransitionID;
For more information, refer to MySQL's Insert...Select Syntax

Sub queries in Yii

I have the following mysql query which works well in phpmyadmin when i execute it :
"SELECT * FROM accounts_users WHERE id = ( SELECT teacher_id FROM general_teacher_student_associations WHERE student_id = 509 )";
But when i execute via Yii, it breaks :
$query = "SELECT * FROM accounts_users WHERE id = ( SELECT teacher_id FROM general_teacher_student_associations WHERE student_id =509 )";
$command = Yii::app()->db->createCommand($query);
$teachers_list = $command->query();
return $teachers_list;
509 is a dynamically fetched value.
1. What am i doing wrong?
2. Can this be done in a better way?
/******Edited***********/
Found the error : The sub query returns more than one row. Can i use single query to fetch all the values other than using a foreach loop and then inside that executing another query?
Solution : (Accepting Daniels answer since his comment actually solved the issue)
$query = "SELECT * FROM accounts_users WHERE id IN ( SELECT teacher_id FROM general_teacher_student_associations WHERE student_id =509 )";
$command = Yii::app()->db->createCommand($query);
$teachers_list = $command->queryAll();
return $teachers_list;
p.s: This is an edition work and i am not allowed to touch model and hence using model relations is out of window and thats why i ended up with this
Try:
$teachers_list = Yii::app()->db->createCommand()->select('ausers.*')
->from('accounts_users ausers')
->join('( SELECT teacher_id FROM general_teacher_student_associations WHERE student_id = 509 ) as teachers ON teachers.teacher_id = ausers.id')
->queryRow();

SQL - Make this statement faster i.e. less duration, reads

Given the following tables:
Orders (OrderID, OrderStatus, OrderNumber)
OrderItems(OrderItemID, OrderID, ItemID, OrderItemStatus)
Orders: 2537 records
Order Items: 1319 records
I have created indexes on
Orders(OrderStatus)
OrderItems(OrderID)
OrderItems(OrderItemStatus)
I have the following SQL statement (generated by LinqToSql) which when executed, has:
- duration = 8789
- reads = 7809.
exec sp_executesql N'SELECT COUNT(*) AS [value]
FROM [dbo].[Orders] AS [t0]
WHERE ([t0].[OrderStatus] = #p0) OR (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[OrderItems] AS [t1]
WHERE ([t1].[OrderID] = [t0].[OrderID]) AND ([t1].[OrderItemStatus] = #p1)
))',N'#p0 nvarchar(2),#p1 nvarchar(2)',#p0=N'KE',#p1=N'KE'
Is there anything else which I can do to make it faster?
make all those nvarchars parameters varchars if the columns in the table are varchars
))',N'#p0 varchar(2),#p1 varchar(2)',#p0=N'KE',#p1=N'KE'
See also here: sp_executesql causing my query to be very slow
Count on a single index rather than *
This might generate some better sql.
IQueryable<int> query1 =
from oi in db.OrderItems
where oi.OrderItemStatus == theItemStatus
select oi.OrderID;
IQueryable<int> query2 =
from o in db.Orders
where o.OrderStatus == theOrderStatus
select o.OrderID;
IQueryable<int> query3 = query1.Concat(query2).Distinct();
int result = query3.Count();