Zend Framework 2 Sql Select with OR and AND - zend-framework2

I want to make this query using Zend\Db\Sql\Select:
SELECT table1.* FROM table1
INNER JOIN table2 ON table1.columnA = table2.columnB
INNER JOIN table3 ON table1.columnC = table3.columnD
WHERE (table2.column2 = 2 or table3.column3 = 3) and table1.column1 = 1
ORDER BY table1.columnE ASC LIMIT 1
I have this code so far:
/*#var $db Adapter */
$db = $this->getServiceLocator()->get('db');
$sql = new Sql($db);
$select = $sql->select();
$select->from('table1');
$select->join('table2','table1.columnA = table2.columnB',array());
$select->join('table3','table1.columnC = table3.columnD',array());
$select->where(array('table2.column2' => 2, 'table2.column3' => 3), Predicate\PredicateSet::OP_OR);
$select->where(array('table1.column1' => 1),Predicate\PredicateSet::OP_AND);
$select->order('table1.columnE ASC');
$select->limit(1);
$statement = $sql->prepareStatementForSqlObject($select);
$resultSet = $statement->execute();
But doesn't works, because produce this one (without the "(" and ")" for the OR):
SELECT table1.* FROM table1
INNER JOIN table2 ON table1.columnA = table2.columnB
INNER JOIN table3 ON table1.columnC = table3.columnD
WHERE table2.column2 = 2 or table3.column3 = 3 and table1.column1 = 1
ORDER BY table1.columnE ASC LIMIT 1
What can I do?

from the top of the head using Where fluent interface:
$select->where
->nest
->equalTo('table2.column2', 2)
->or
->equalTo('table2.column3', 3)
->unnest
->and
->equalTo('table1.column1', 1);

I would do something like:
$where = new \Zend\Db\Sql\Where();
$where
->nest()
->equalTo('table2.column2', 2)
->or
->equalTo('table2.column3', 3)
->unnest()
->and
->equalTo('table1.column1', 1);
$select->where($where)
Just because this way your $select keep being an implementation of Zend\Db\Sql\SqlInterface
while doing
$select->where
->nest
will return an instance of a Zend Sql operator. Which is not bad but then you can't just do
$statement = $sql->prepareStatementForSqlObject($select);
$resultSet = $statement->execute();

Related

Typeorm subquery add select

I am new for using typeorm and this is the second time I am confused with typeorm, I have the following query :
SELECT t1.a,t1.b,t2.a
(SELECT TOP 1 t1.a
FROM table1 t1
WHERE t1.b = t2.a
ORDER BY t1.a DESC
) AS MaxT1
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.a = t2.a
I tried this:
let query = await getManager()
.createQueryBuilder(Bid, 'bid')
.select([
'l.ID_anv_Lot',
'l.LotNumber',
'w.WineryName',
'bid.BidAmount',
'bid.ProxyBidAmount',
'er.ID_Contact'
])
.addSelect(Table1, t1)
.innerJoin(Lot, 'l', 'l.lotNumber = bid.lotNum AND l.paddleNumber = bid.paddleNumber')
but the result is all of the rows on table1
This Example may help you to perform sub query execution:
const posts = await connection.getRepository(Post)
.createQueryBuilder("post")
.where(qb => {
const subQuery = qb.subQuery()
.select("usr.name")
.from(User, "usr")
.where("usr.registered = :registered")
.getQuery();
return "post.title IN " + subQuery;
})
.setParameter("registered", true)
.orderBy("post.id")
.getMany();
You can use subselects in SELECT statements:
let query = await this.createQueryBuilder('t1')
.select()
.innnerJoin('t1.t2', 't2', 't1.a = t2.a')
.addSelect(subQuery => {
return subQuery
.select('_t1.a')
.from(Table1, '_t1')
.where('_t1.b = t2.a');
}, 'MaxT1')
.getRawMany()
You can find more here: https://orkhan.gitbook.io/typeorm/docs/select-query-builder

SQL Raw data query

Hi I am trying to query some data like this
$sql = "SELECT *
FROM company";
$stmt = $this->getDbAdapter()->query($sql, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);
if ($stmt instanceof \Zend\Db\ResultSet\ResultSet) {
foreach ($stmt as $row) {
$entities[] =$row;
}
}
But I get an 500 Internal server error, Is there something wrong with this code?
I have done this one an it work fine.
$sql = "SELECT company.*,address_home.*,address_billing.*, T1.*
FROM company AS company
INNER JOIN address AS address_home ON company.address_id_fk = address_home.address_id
INNER JOIN address AS address_billing ON company.billing_address_id_fk = address_billing.address_id
INNER JOIN (SELECT company_id_fk,
max(case when company_role_id_fk = '1' then 'true' end) isClient,
max(case when company_role_id_fk = '2' then 'true' end) isSupplier
FROM company_role_company_maps AS crcm
WHERE crcm.company_id_fk = $id
GROUP BY company_id_fk) AS T1
ON(company.company_id = T1.company_id_fk)
WHERE company.company_id = $id";
$resultset = $this->getDbAdapter()->query($sql, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);
$current = $resultset->current()->getArrayCopy();
But for some reason when I do the loop i get the error.
I try this to see If I cud catch something.
$sql = "SELECT *
FROM company";
$stmt = $this->getDbAdapter()->query($sql, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);
if ($stmt instanceof \Zend\Db\ResultSet\ResultSet) {
try{
foreach($stmt as $row) {
var_dump($row);
}
}catch(\Exception $e){
var_dump($e->getMessage());
}
}
But I just got the Internal server error message (There is a problem with the resource you are looking for, and it cannot be displayed.)

ZEND 2. Union . Add Limit to UNION query

I have an sql query like the one below and i would like to create this in Zend Framework 2.
( SELECT id AS id FROM exp_personal_data ORDER BY town ) UNION ( SELECT id AS id FROM pd_unregister )
I would like to have union and add to this LIMIT, ORDER BY etc.
$this->_select->combine($selectPdContest, 'union all');
When i write the query like this.
$this->_select->combine($selectPdContest, 'union all')->limit('10);
Query looks like this:
( SELECT id AS id FROM exp_personal_data ORDER BY town LIMIT 10 ) UNION ( SELECT id AS id FROM pd_unregister )
The limit is added only to firs select. I want the limit will to be added like this.
( SELECT id AS id FROM exp_personal_data ORDER BY town ) UNION ( SELECT id AS id FROM pd_unregister ) LIMIT 10
How make this in Zend framework 2?
Solution 1 (simple):
$adapter = $this->tableGateway->getAdapter();
$resultSet = $adapter->query("(SELECT user_id AS id FROM user ORDER BY id) UNION (SELECT account_id AS id FROM account) LIMIT 10",$adapter::QUERY_MODE_EXECUTE);
print_r($resultSet->toArray());die;
Solution 2 (Complex):
use Zend\Db\Sql\Sql;
use Zend\Db\Sql\Select;
//sql query first part
$adapter = $this->tableGateway->getAdapter();//the db connection adapter
$select = new Select('user');
$select->columns(array('id' => 'user_id'));
$select->order('id');
$sql = new Sql($adapter);
$statement = $sql->getSqlStringForSqlObject($select);
//sql query second part
$select2 = new Select('account');
$select2->columns(array('id' => 'account_id'));
$sql = new Sql($adapter);
$statement2 = $sql->getSqlStringForSqlObject($select2);
//combine the two statements into one
$unionQuery = sprintf('%s UNION %s','('.$statement = $sql->getSqlStringForSqlObject($select).')',
'('.$statement2 = $sql->getSqlStringForSqlObject($select2).') LIMIT 10');
//execute the union query
$resultSet = $adapter->query( $unionQuery, $adapter::QUERY_MODE_EXECUTE);
print_r($resultSet->toArray());die;
Add these lines will work,
$select1 = new Select();
$select1->combine($selectPdContest, 'union all');
$select3 = new Select();
$oneTwo = $select3->from(['sub' => $select1])->limit(10);

How to simulate Subqueries in the ON Clause in Vertica database?

Hy everbody , i am having some trouble in transforming a query that has a set of subqueries in the ON clause.
The initial code was created in SQL Server and i have changed to work on Vertica.
This is the code :
SELECT
DISTINCT DocFinanceiro.AutoId AS AutoId,
DocFinanceiro.Classe AS ClasseDoc,
EspecPrestador.Seq AS Sequencia,
PrestadorServico.Codigo AS CodigoPrest,
PessoaPrest.Nome AS NomePrestador,
DocFinanceiro.CompFinanceira AS CompFinanceira,
EspecialidadeServico.Nome AS Especialidade,
ClassePrestador.Nome AS ClsPrestador,
RegistroPessoa.Numero AS RegistroINSS,
RegistroPessoa.Tipo AS TipoRegPessoa,
DocFinanceiro.DataVencimento AS DataVencimentoDocFin
FROM DocFinanceiro
INNER JOIN ClasseDocFinanceiro
ON DocFinanceiro.Classe = ClasseDocFinanceiro.Codigo
INNER JOIN ItemFinanceiro ON DocFinanceiro.AutoId = ItemFinanceiro.Documento
INNER JOIN ClasseApropriacaoFinan
ON ItemFinanceiro.ClasseApro = ClasseApropriacaoFinan.Codigo
INNER JOIN ContratoFinanceiro
ON DocFinanceiro.ContratoFinanceiro = ContratoFinanceiro.AutoId
INNER JOIN Pessoa ON ContratoFinanceiro.Pessoa = Pessoa.AutoId
INNER JOIN GeradorItemFinan
ON ItemFinanceiro.AutoId = GeradorItemFinan.ItemFinan
INNER JOIN PrestadorServico
ON ContratoFinanceiro.AutoId = PrestadorServico.ContratoFinanceiro
INNER JOIN Pessoa PessoaPrest ON PrestadorServico.Pessoa = PessoaPrest.AutoId
INNER JOIN TipoValorFinan
ON ClasseApropriacaoFinan.TipoValor = TipoValorFinan.Codigo
INNER JOIN ClasseContratoFinanceiro
ON ContratoFinanceiro.Classe = ClasseContratoFinanceiro.AutoId
INNER JOIN ClassePrestador
ON PrestadorServico.Classe = ClassePrestador.Codigo
LEFT JOIN EspecPrestador
ON EspecPrestador.Prestador = PrestadorServico.AutoId
AND EspecPrestador.Seq = 1
LEFT JOIN EspecialidadeServico
ON EspecialidadeServico.AutoId = EspecPrestador.Especialidade
LEFT JOIN RegistroPessoa ON PessoaPrest.AutoId = RegistroPessoa.Pessoa
--This is the part where i getr stuck
AND
(
RegistroPessoa.AutoId =
(
SELECT
RegistroPessoa.AutoId
FROM RegistroPessoa
WHERE RegistroPessoa.Pessoa = PessoaPrest.Autoid
AND (RegistroPessoa.Tipo = 1 OR RegistroPessoa.Tipo = 1) order by 1 limit 1
)
)
--until here
WHERE (GeradorItemFinan.TipoGerador = 1)
AND (DocFinanceiro.CompFinanceira = 1)
AND (PrestadorServico.AutoId = 1)
AND DocFinanceiro.CompSeq = 1
AND (DocFinanceiro.Numero IS NOT NULL)
AND (DocFinanceiro.Classe <> 1)
ORDER BY AutoId, Sequencia
;
If anybody has any ideas it would be great !!
try replace
RegistroPessoa.AutoId = (SELECT...)
to
RegistroPessoa.AutoId IN (SELECT...)
and use aliases for table short names

Nested query in Linq

I have three tables. I have to retrieve the data using Linq statement. My three table names are A,B,C. I connected join for connecting two tables A and B based on the id's like:
select ol, fN, LN, ci, co
from member
join details
on member_id = details_id
where details_id in
(select contacts_id from contacts where
contacts_id1 = 1 and contacts_usr_id = 1)
I am able to write the query up to the where condition, how can I write the query for the inner while condition?
you can try this:
var idlist = (from tbl in table3
where tbl.usr_id == 1 && tbl.contacts_id == 1
select tbl.contacts_id ).ToList();
var x = from A in table1
from B in table2 where A.user_id == B.user_id
&& idlist.Contains(A.user_id)
select new { a = A.a, b = A.b, c = A.c, d = B.d, e = B.e };
check and let me know if that work.
Try flipping the query upside down. How about the following:
var query =
from t3 in table3
where t3.user_id = 1 && t3.contacts_id = 1
join t2 in table2 on t3.contacts_id equals t2.usr_id
join t1 in table1 on t2.usr_id equals t1.userid
select new {t2.a, t2.b, t2.c, t1.d, t1.e};

Resources