how to fit complex mysql query into zf2 - zend-framework2

i am unable to fit my query into zf2 query, i can fit simple join query but i can not write for more complex sub queries.
please help me to do this.
SELECT `created_date` FROM `salesmodule_discussed_topic` dt WHERE dt.`meeting_id` IN(
SELECT ma.`meeting_id` FROM `salesmodule_meeting_agent` ma WHERE ma.`agent_id`=30547
)
public function getLastmeetingdate() {
$select = new Select();
$select->from(array('dt' => 'salesmodule_discussed_topic'));
$select->columns(array('created_date'));
$select->where(array('ma.`agent_id` => 30547));
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet->buffer();
}

The previous example is bad because has an sql injections. You need make a subquery using Select.
public function getLastmeetingdate() {
$subQuery = new Select();
$subQuery->from(array('ma' => 'salesmodule_meeting_agent'));
$subQuery->columns(array('meeting_id'));
$subQuery->where(array('ma.agent_id' => 30547));
$select = new Select();
$select->from(array('dt' => 'salesmodule_discussed_topic'));
$select->columns(array('created_date'));
$select->where->in('dt.meeting_id', $subQuery);
return $this->tableGateway->selectWith($select);
}

public function fetchAllSubQuery($id = '') {
$columns = array("*");
$where = "main_booking_id IN (SELECT
b1.`main_booking_id`
FROM
`booking_sector` b1
WHERE b1.`connected_booking_id` = '$id' OR b1.`main_booking_id` = '$id') ";
$resultSet = $this->tableGateway->select(function (Select $select) use ($where,$columns) {
$select->where($where);
$select->columns($columns);
});
$resultSet->buffer();
// $resultSet->next();
return $resultSet;
}

Related

Select Columns to return when joining a table with Zend\Db\Sql

I just want to return one column (per.cd_acao), so I tried something like:
$select->from(array('act' => 'tb_acao'))
->join(array('per' => 'tb_perfil_acao'),
'per.cd_acao = act.cd_acao',
array('cd_acao'),
$select::JOIN_INNER
);
but this is producing a query string like:
SELECT "act".*, "per"."cd_acao" AS "cd_acao" FROM "tb_acao" AS "act" INNER JOIN "tb_perfil_acao" AS "per" ON "per"."cd_acao" = "act"."cd_acao" WHERE "per"."sq_perfil" = '89'
it is bringing all columns from the first table, when I want none. What am I missing here?
Update
summarizing: When I don't inform 'columns' in a select object, it defaults to return all columns to me. But when I'm joining, I don't want any columns to be returned by the first table.
An empty array will suffice
$select->from(array('act' => 'tb_acao'))
->columns(array())
->join(array('per' => 'tb_perfil_acao'),
'per.cd_acao = act.cd_acao',
array('cd_acao'),
$select::JOIN_INNER
);
Try with this query
use Zend\Db\Sql\Sql;
protected $tableGateway;
public $adapter;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
publice function getData(){
$adapter = $this->tableGateway->getAdapter();
$sql = new Sql($adapter);
$select = $sql->select();
$select->from('tb_acao')
->join('per'),
'per.cd_acao = act.cd_acao',
array('cd_acao'),
);
$statement = $sql->prepareStatementForSqlObject($select);
$results = $statement->execute();
return $results;
}

LINQ Join with where condition

I can use LINQ's Join with Lambda notations no problem, but I can't work out how one would then add a where condition.
var q = query.Join(context.CustomerIds,
x => x.CustomerId,
y => y.CustomerId,
(x, y) => new CustomerLookupResult()
{
dob = x.DateOfBirth.ToString(),
forenames = x.Forenames,
surname = x.Surname,
loyaltyNo = y.Identifier,
customerId = x.CustomerId
});
The table I'm joining the first to contains the loyaltyNo in its Identifier column, but also contains other information in the same column and so uses a second column IdentifierTypeCode to allow filtering.
So how do I now add .Where(x => x.IdentifierTypeCode == "LOYALTY") like I would in SQL. Appending this to end refers to the new object.
You could apply your Where before doing the join.
var q = customerLoyalties
.Where(x => x.IdentifierTypeCode == "LOYALTY")
.Join(customers,
x => x.CustomerId,
y => y.CustomerId,
(x, y) => new CustomerLookupResult()
{
CustomerId = y.CustomerId,
Name = y.Name,
IdentifierTypeCode = x.IdentifierTypeCode
});
You can also use this way to achieve that using Linq.
var match = from t1 in context.orders
join t2 in context.orderdetails on
new { t1.OrderID } equals
new { t2.OrderID }
join t3 in context.products on
new { t2.ProductID } equals
new { t3.ProductID }
where t3.ProductID == id
select t3;
return match.ToList();
The first parameter to the Join takes any IEnumerable, so you can apply the Where at that point, or earlier
var q = query.Join(context.CustomerIds.Where(x=>x.IdentifierTypeCode=="LOYALTY"),
x => x.CustomerId,
y => y.CustomerId,
(x, y) => new CustomerLookupResult()
{
dob = x.DateOfBirth.ToString(),
forenames = x.Forenames,
surname = x.Surname,
loyaltyNo = y.Identifier,
customerId = x.CustomerId
});
alternatively, if you don't like to put too much on one line:
var filteredLoyalties = context.CustomerIds.Where(x=>x.IdentifierTypeCode=="LOYALTY");
var q = query.Join(filteredLoyalties,
...

Clauses OR Where in Zend framework 2

I'm new to ZF2.
How can I write a query like this?
SELECT * FROM users WHERE id = 1 AND status != 2
My code Model:
public function getUser($where = array())
{
$select = $this->sql->select();
$select->from(self::TABLE);
$select->where($where);
$select->order('name ASC');
return $statement->execute();
}
I am using: Zend\Db\Sql
Thanks.
Look at the docs here.
So $where can be a string or Closure, too.
Call it in your case like:
$user = $object->getUser('status != 2');
Oh, I missed the first condition:
$user = $object->getUser(array('id = 1', 'status != 2'));
EDIT:
You can for sure leave the = array() default value. I don't know why but I confused it with type hinting. (array $where)
public function getUser( where = array() ) {
$select = $this->sql->select();
$select->from(self::TABLE);
$select
->where->nest()
->equalTo( 'id' => where['id'] )
->or
->notEqualTo( 'status' => where['status'] )
->unnest();
$select->order('name ASC');
return $statement->execute();
}
use like this:
getUser( array(
'id' => 1,
'where' => 2,
) );

Returning property and count columns together in Neo4jClient Cypher Query

I have a Cypher query likes this:
START n=node:permit_idx(PmtID= "111")
Match n-[:Assinged]->m<-[:Assinged]-p
RETURN p.PmtID, count(m);
I got error when I try to do it using Neo4jClient Cypher Query
var results = graphClient
.Cypher
.Start(new { n = Node.ByIndexLookup("permit_idx", "PmtID", "111") })
.Match("Match n-[:Assigned]->m<-[:Assigned]-p")
.Return((m, p) => new
{
PDPmtID = "p.PmtID",
MCount = "count(m)"
})
.Results;
If only need to return one property or one count, we can use
.Return<int>("count(m)");
But how to return property and count together?
.Return((m, p) => new
{
PDPmtID = Return.As<int>("p.PmtID"),
MCount = m.Count()
})
Or, preferred right now:
.Return((m, p) => new
{
Permit = p.As<Permit>(),
MCount = m.Count()
})
You need to use the custom text option in your compound Return clause:
.Return((m, p) => new
{
PDPmtID = Return.As<int>("p.PmtID"),
MCount = Return.As<int>("count(m)")
})
(This is based on the documentation for the Neo4jClient)

zf2 select columns from joined tables - how?

I feel like I must me missing something very simple. It's a very simple task, all I want to do is get something like:
SELECT * FROM lookup_items
JOIN lookup ON lookup_items.lookup_id = lookup.id
This returns all the columns for all the joined tables, in regular SQL. Here's my attempt in zf2:
$select = new Select();
$select->from('lookup_items');
$select->join('lookup', 'lookup_items.lookup_id = lookup.id');
The result set only includes the columns in 'lookup_items'. I've tried various ways to get the 'lookup' columns, including:
$select->columns(array('lookup_items.*', 'lookup.*'));
But they all just blow up. Surely there's a way to do this, and it's just so simple I'm missing it completely.
I thought a simple example would be avoid confusion, but here's more code:
class LookupItemsTable extends AbstractTableGateway
{
public function getList($resource)
{
$system_name = str_replace('*', '%', strtoupper($resource));
$joinTable = 'lookup';
$select = new Select();
$select->from($this->table);
$select->join($joinTable, "{$this->table}.lookup_id = {$joinTable}.id");
$where = array();
$where[] = "{$this->table}.enabled is true";
$where[] = "{$joinTable}.enabled is true";
$where[] = "UPPER({$joinTable}.system_name) ilike '{$system_name}'";
$select->where($where);
$sort[] = 'sort_order ASC';
$sort[] = 'value ASC';
$select->order($sort);
$rowset = $this->selectWith($select);
return $rowset;
}
}
Where:
$resource = $this->params()->fromRoute('resource', 'BUSINESS');
And $this->table is 'lookup_items'. Really all I want to do is get columns from both joined tables. I guess there's a zf2 way to just make a straight SQL statement without all the OO falderal, so I could just force it that way. But I'd rather work within the framework as much as possible.
Just change this line
$select->join('lookup', 'lookup_items.lookup_id = lookup.id');
to
$select->join('lookup', 'lookup_items.lookup_id = lookup.id', array('lookupcol1', 'lookupcol2');
Raj answer is the best one but it only works if you don't forget to add these fiels in your LookupItems model.
class LookupItems
{
// Your lookup_items fields here...
...
// And the added lookup fields here, the ones you add in the array
public $lookupcol1;
public $lookupcol2;
And in the exchangeArray method :
public function exchangeArray($data)
{
// .... your fields, and the new ones
$this->lookupcol1 = (! empty($data['lookupcol1'])) ? $data['lookupcol1'] : null;
$this->lookupcol2 = (! empty($data['lookupcol2'])) ? $data['lookupcol2'] : null;
}
I figured it out.
Added this:
$select->columns(array('*'));
And then this near the end:
$sql = new Sql($this->adapter);
$statement = $sql->prepareStatementForSqlObject($select);
$rowset = $statement->execute();
This returns the expected result, with the caveat that now my rows are returned as associative arrays instead of objects.
This is how you can create queries with join in zf2.
$resultSet = $this->select(function (Select $select) {
// omit the table name
//$select->from('foo');
$select->join('users', "users.id foo.createdby", 'firstname', '');
$select->order('id ASC');
// echo $select->getSqlString();// to print your query
});
$entities = array();
foreach ($resultSet as $row) {
$entity = new Entity\Foo();
$entity->setId($row->id)
->setFullname($row->fullname)
->setCaseid($row->caseid)
->setTestimonial($row->testimonial)
->setSortorder($row->sortorder)
->setActive($row->active)
->setCreated($row->created)
->setModified($row->modified)
->setFirstname($row->firstname)
->setCreatedby($row->createdby);
$entities[] = $entity;
}
return $entities;

Resources