How can I join a subquery using Zend_Db_Select - zend-framework

How would I construct this query using Zend_Db_Select?:
SELECT users.user_id, email_address, t1.value as 'languages'
FROM users
LEFT JOIN (
SELECT
user_id
, field_id
, GROUP_CONCAT(value SEPARATOR ',') AS value
FROM user_multivalued
WHERE field_id=25
GROUP BY user_id, field_id) t1
ON t1.user_id = users.users_id
WHERE list_id = 45

$user_multivalued = $db
->select()
->from('user_multivalued', array(
'user_id',
'field_id',
new Zend_Db_Expr("GROUP_CONCAT(value SEPARATOR ',') AS value")
))
->where('field = ?', 25)
->group('user_id')
->group('field_id')
;
$select = $db
->select()
->from('users', array('user_id', 'email_address'))
->joinLeft(
array('t1' => $user_multivalued),
't1.user_id = users.user_id',
array('languages'=>'value')
)
->where('list_id = ?', 45)
;

Related

Eloquent Query builder using orderby count having with clause

select `tableA`.*, (select count(*) from `tableB` where `tableA`.`id` =
`tableB`.`sid` and `tableB`.`status` = 'true' ) as `count`, (select name from
`tableC` where `tableA`.`id` = `tableC`.`sid` and (`CCol` = 'en' or `CCol` = 'id')
order By field(`CCol`, 'id','en') limit 1) as CCol from `tableA` where
`status` = 'true' order by `count` desc, `CCol` asc limit 10
Could you help me out to change this query in eloquent ORM builder. I have tried but couldnt found out how to add where clause in count
$A = $A->withCount('B')
->orderBy('count', 'desc');
$A->orderBy('CCol', 'ASC');

TYPO3: How convert SQL statement into typo3 PDO

I'm having a problem with SQL(subqueries) statement when I trying to implement with "queryBuilder" at TYPO3. Please can you help me with this case(convert SQL statament to TYPO3 "queryBuilder"). Thanks!
SQL Statement:
SELECT * FROM table_1 AS t1
INNER JOIN table_2 AS t2 ON t1.id = t2.id
WHERE t2.date = (SELECT MAX(date) FROM t2 AS t2_Tmp WHERE t2_Tmp.id = t2.id)
I tried with this code(example):
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('table2');
return $queryBuilder->select('*')
->from('table2')
->innerJoin(
'table2',
'table1',
't1',
$queryBuilder->expr()->eq('t1.id', $queryBuilder->quoteIdentifier('t2.id'))
)
->where(
$queryBuilder->expr()->eq('t2.date',
$queryBuilder->addSelectLiteral($queryBuilder->expr()->max('t2.date', 'date'))
->from('t2','t2_tmp')
->where($queryBuilder->expr()->eq('t2_tmp.id', $queryBuilder->quoteIdentifier('t2.id')))
)
)
->execute()
->fetchAll();
I found a solution for this case and work for me.
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('table1');
$subQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('table2');
$queryBuilder->select('*')
->from('table1', 't1')
->innerJoin(
't1',
'table2',
't2',
$queryBuilder->expr()->eq('t2.t1_uid', $queryBuilder->quoteIdentifier('t1.uid')))
->where(
$queryBuilder->expr()->eq('t2.date', '(' . $subQueryBuilder->addSelectLiteral(
"MAX(date) FROM t2 AS t2_tmp WHERE t2_tmp.t1_uid = t2.t1_uid"
) . ')'
)
)
->execute()
->fetchAll();
I think you can try something like that :
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('table2');
return $queryBuilder->select('*')
->from('table1', 't1')
->innerJoin(
't1',
'table2',
't2',
$queryBuilder->expr()->eq('t1.id', $queryBuilder->quoteIdentifier('t2.id'))
)
->where(
$queryBuilder->expr()->eq('t2.date',
$queryBuilder->addSelectLiteral("(SELECT MAX(date) FROM t2 AS t2_Tmp WHERE t2_Tmp.id = t2.id)")
)
)
->execute()
->fetchAll();

How do I get the max from a partitioned query using Rank ()

I want the result to return the max Rank when partitioned using the rank function.
I am using the following query.
SELECT DISTINCT dbo.pomst.co_num
,dbo.pomst.wh_num
,dbo.pomst.po_number
,dbo.pomst.po_suffix
,dbo.pomst.vendor_id
,dbo.item.uom
,dbo.item.upc_num
,dbo.item.item_desc
,RIGHT(dbo.auditlog.pallet_id, 8) AS pallet_id
,dbo.auditlog.abs_num
,dbo.auditlog.item_qty
,dbo.auditlog.lot
,dbo.auditlog.packer
,auditlog.comments
,auditlog.date_time
,rank() OVER (
PARTITION BY auditlog.comments ORDER BY auditlog.date_time ASC
) AS CorrectTrans
FROM dbo.auditlog
INNER JOIN dbo.pomst ON dbo.auditlog.co_num = dbo.pomst.co_num
AND dbo.auditlog.wh_num = dbo.pomst.wh_num
AND dbo.auditlog.po_number = dbo.pomst.po_number
AND dbo.auditlog.po_suffix = dbo.pomst.po_suffix
INNER JOIN dbo.item ON dbo.auditlog.co_num = dbo.item.co_num
AND dbo.auditlog.wh_num = dbo.item.wh_num
AND dbo.auditlog.abs_num = dbo.item.abs_num
WHERE (dbo.pomst.co_num = 'AC01')
AND (dbo.pomst.wh_num = 'KU22')
AND (dbo.pomst.row_status = 'C')
AND (dbo.auditlog.trans_type = 're')
AND item_qty NOT LIKE '-%'
I figured it out! I was trying to get the max result of a rank, but if I flip order of rank from asc to desc and use a CTE I can select the the results that always have 1 as the rank as opposed to trying to get the Max. I would still like to know how to get the Max rank but this solution suits my needs.
;with cte as
(SELECT DISTINCT dbo.pomst.co_num
,dbo.pomst.wh_num
,dbo.pomst.po_number
,dbo.pomst.po_suffix
,dbo.pomst.vendor_id
,dbo.item.uom
,dbo.item.upc_num
,dbo.item.item_desc
,RIGHT(dbo.auditlog.pallet_id, 8) AS pallet_id
,dbo.auditlog.abs_num
,dbo.auditlog.item_qty
,dbo.auditlog.lot
,dbo.auditlog.packer
,auditlog.comments
,auditlog.date_time
,rank() OVER (
PARTITION BY auditlog.comments ORDER BY auditlog.date_time desc
) AS CorrectTrans
FROM dbo.auditlog
INNER JOIN dbo.pomst ON dbo.auditlog.co_num = dbo.pomst.co_num
AND dbo.auditlog.wh_num = dbo.pomst.wh_num
AND dbo.auditlog.po_number = dbo.pomst.po_number
AND dbo.auditlog.po_suffix = dbo.pomst.po_suffix
INNER JOIN dbo.item ON dbo.auditlog.co_num = dbo.item.co_num
AND dbo.auditlog.wh_num = dbo.item.wh_num
AND dbo.auditlog.abs_num = dbo.item.abs_num
WHERE (dbo.pomst.co_num = 'AC01')
AND (dbo.pomst.wh_num = 'KU22')
AND (dbo.pomst.row_status = 'C')
AND (dbo.auditlog.trans_type = 're')
AND item_qty NOT LIKE '-%'
)
Select * from cte
where CorrectTrans = 1
Add select and group by and use your existing query as a sub query.
Try ..
select max([CorrectTrans]), Vendor_Id, Item_qty, Lot, Pallet_id
from (
-- Your existing query --
SELECT DISTINCT dbo.pomst.co_num
,dbo.pomst.wh_num
,dbo.pomst.po_number
,dbo.pomst.po_suffix
,dbo.pomst.vendor_id
,dbo.item.uom
,dbo.item.upc_num
,dbo.item.item_desc
,RIGHT(dbo.auditlog.pallet_id, 8) AS pallet_id
,dbo.auditlog.abs_num
,dbo.auditlog.item_qty
,dbo.auditlog.lot
,dbo.auditlog.packer
,auditlog.comments
,auditlog.date_time
,rank() OVER (
PARTITION BY auditlog.comments ORDER BY auditlog.date_time ASC
) AS CorrectTrans
FROM dbo.auditlog
INNER JOIN dbo.pomst ON dbo.auditlog.co_num = dbo.pomst.co_num
AND dbo.auditlog.wh_num = dbo.pomst.wh_num
AND dbo.auditlog.po_number = dbo.pomst.po_number
AND dbo.auditlog.po_suffix = dbo.pomst.po_suffix
INNER JOIN dbo.item ON dbo.auditlog.co_num = dbo.item.co_num
AND dbo.auditlog.wh_num = dbo.item.wh_num
AND dbo.auditlog.abs_num = dbo.item.abs_num
WHERE (dbo.pomst.co_num = 'AC01')
AND (dbo.pomst.wh_num = 'KU22')
AND (dbo.pomst.row_status = 'C')
AND (dbo.auditlog.trans_type = 're')
AND item_qty NOT LIKE '-%'
-- =======================================
) x
group by Vendor_id, Item_qty, Lot, Pallet_id

Ordinary query to Zend format Query?

manually I constructed a query... I'm facing struggle to construct in zend,
e.i select inside select
these is my query,
SELECT * FROM (
SELECT t1.eventId,t1.start_date,t1.end_date, COUNT(*) pos FROM events t1
LEFT JOIN events t2
ON t2.start_date = t1.start_date AND t2.eventId <= t1.eventId
GROUP BY
t1.eventId,t1.start_date
) t
WHERE
pos <= 3;
$query = $database->select ()
->from ('events AS t1', array (
'eventId',
'start_date',
'end_date',
new Zend_Db_Expr ('COUNT(*) AS pos')
))
->joinLeft ('events AS t2', 't2.start_date = t1.start_date AND t2.eventId <= t1.eventId', array ())
->group ('t1.eventId,t1.start_date');
$outer_query = $database->select ()
->from ($query)
->where ('pos <= 3');

SQL- retrieving distinct ID

I have a table with the following data:
ID NAME ATTRIBUTE CODE
=============================
1 XX MM GC
1 XX ST GC
2 ZZ LL GC
2 ZZ ST GC
3 AA MM PC
I need the ID, name of from the table which contains either MM Attribute or GC code but not both. Like the query should retrieve the ID numbers only 2 and 3 but not 1 .
How do I do that?
Select Id, Name
From #t
Where (Attribute = 'MM' Or Code = 'GC')
And Id Not In (Select Id From #t
Where (Attribute = 'MM' And Code = 'GC'))
select distinct T1.ID,
T1.NAME
from T as T1
where (T1.ATTRIBUTE = 'MM' or T1.CODE = 'GC') and
not exists (select *
from T as T2
where T1.ID = T2.ID and
T2.Attribute = 'MM' and
T2.CODE = 'GC')
Result:
ID NAME
2 ZZ
3 AA
Try this:
select distinct ID
from TableName
where (Attribute = 'MM' or Code = 'GC')
and not (Attribute = 'MM' AND Code = 'GC')
Try this:
SELECT ID, NAME
FROM <YOUR-TABLE-NAME>
WHERE
(ATTRIBUTE = 'MM' AND CODE <> 'GC') OR
(ATTRIBUTE <> 'MM' AND CODE = 'GC') ;
select distinct Id, Name
from tbl?
where
(attribute = 'MM' or code = 'GC')
and not (attribute = 'MM' and code = 'GC')
(
SELECT ID, NAME FROM TableName WHERE CODE = 'GC'
EXCEPT
SELECT ID, NAME FROM TableName WHERE ATTRIBUTE = 'MM'
)
UNION
(
SELECT ID, NAME FROM TableName WHERE ATTRIBUTE = 'MM'
EXCEPT
SELECT ID, NAME FROM TableName WHERE CODE = 'GC'
)