Zend_DB_Select : why are all fields returned? - zend-framework

public function getWorksheetData($id) {
/** create the following query using select object:
SELECT wc.label, wd.notes FROM worksheet_data wd
LEFT JOIN worksheet_columns wc ON wd.column_id = wc.id;
*/
$id = (int) $id;
$select = $this->_db->select()
->from(array('wd'=>'worksheet_data'),
array('wc.label','wd.notes'))
->join(array('wc'=>'worksheet_columns','wd.column_id = wc.id'))
->where("wd.id = :worksheet_id");
$results = $this->_db->fetchAll($select, array('worksheet_id' => $id),Zend_Db::FETCH_ASSOC);
return array('results'=>$results);
}
Why does this query become:
SELECT wc.label, wd.notes, wc.* FROM worksheet_data AS wd INNER JOIN worksheet_columns AS wc WHERE (wd.id = :worksheet_id)
and return wc.*?

You need to put an empty array as the third argument to the join method, also the join condition should not be part of the first argument's array, but as the second argument instead (you'll notice that there is not join condition in your query). Join needs at least the first two arguments, this is the method signature:
join(table, join, [columns])
Applying that to your join method:
->join(array('wc'=>'worksheet_columns'),'wd.column_id = wc.id', array())
so:
$select = $this->_db->select()
->from(array('wd'=>'worksheet_data'),
array('wc.label','wd.notes'))
->join(array('wc'=>'worksheet_columns'),'wd.column_id = wc.id', array())
->where("wd.id = :worksheet_id");
gives the output:
SELECT `wc`.`label`, `wd`.`notes` FROM `worksheet_data` AS `wd` INNER JOIN `worksheet_columns` AS `wc` ON wd.column_id = wc.id WHERE (wd.id = :worksheet_id)
The manual says:
To select no columns from a table, use
an empty array for the list of
columns.

Related

Postgresql, how to SELECT json object without duplicated rows

I'm trying to find out how to get JSON object results of selected rows, and not to show duplicated rows.
My current query:
SELECT DISTINCT ON (vp.id) jsonb_agg(jsonb_build_object('affiliate',a.*)) as affiliates, jsonb_agg(jsonb_build_object('vendor',vp.*)) as vendors FROM
affiliates a
INNER JOIN related_affiliates ra ON a.id = ra.affiliate_id
INNER JOIN related_vendors rv ON ra.product_id = rv.product_id
INNER JOIN vendor_partners vp ON rv.vendor_partner_id = vp.id
WHERE ra.product_id = 79 AND a.is_active = true
GROUP BY vp.id
The results that I receive from this is:
[
affiliates: {
affiliate: affiliate1
affiliate: affiliate2
},
vendors: {
vendor: vendor1,
vendor: vendor1,
}
As you can see in the second record, vendor is still vendor1 because there are no more results, so I'd like to also know if there's a way to remove duplicates.
Thanks.
First point : the result you display here above doesn't conform the json type : the keys are not double-quoted, the string values are not double-quoted, having dupplicated keys in the same json object ('{"affiliate": "affiliate1", "affiliate": "affiliate2"}' :: json) is not be accepted with the jsonb type (but it is with the json type).
Second point : you can try to add the DISTINCT key word directly in the jsonb_agg function :
jsonb_agg(DISTINCT jsonb_build_object('vendor',vp.*))
and remove the DISTINCT ON (vp.id) clause.
You can also add an ORDER BY clause directly in any aggregate function. For more information, see the manual.
You could aggregate first, then join on the results of the aggregates:
SELECT a.affiliates, v.vendors
FROM (
select af.id, jsonb_agg(jsonb_build_object('affiliate',af.*)) as affiliates
from affiliates af
group by af.id
) a
JOIN related_affiliates ra ON a.id = ra.affiliate_id
JOIN related_vendors rv ON ra.product_id = rv.product_id
JOIN (
select vp.id, jsonb_agg(jsonb_build_object('vendor',vp.*)) as vendors
from vendor_partners vp
group by vp.id
) v ON rv.vendor_partner_id = v.id
WHERE ra.product_id = 79
AND a.is_active = true

Linq order by using query expression

Is it possible to do orderby expression using linq query expression based on dynamic string parameter? because the query i have is producing weird SQL query
my linq:
var product = from prod in _context.Products
join cat in _context.Categories on prod.CategoryId equals cat.CategoryId
join sup in _context.Suppliers on prod.SupplierId equals sup.SupplierId
orderby sortParam
select new ProductViewModel
{
ProductName = prod.ProductName,
ProductId = prod.ProductId,
QuantityPerUnit = prod.QuantityPerUnit,
ReorderLevel = prod.ReorderLevel,
UnitsOnOrder = prod.UnitsOnOrder,
UnitPrice = prod.UnitPrice,
UnitsInStock = prod.UnitsInStock,
Discontinued = prod.Discontinued,
Category = cat.CategoryName,
Supplier = sup.CompanyName,
CategoryId = cat.CategoryId,
SupplierId = sup.SupplierId
};
where var sortParam = "prod.ProductName"
The code above produces weird sql where order by sortParam is being converted to (SELECT 1). Full query catched by sql profiler below:
exec sp_executesql N'SELECT [prod].[ProductName], [prod].[ProductID], [prod].[QuantityPerUnit], [prod].[ReorderLevel], [prod].[UnitsOnOrder], [prod].[UnitPrice], [prod].[UnitsInStock], [prod].[Discontinued], [cat].[CategoryName] AS [Category], [sup].[CompanyName] AS [Supplier], [cat].[CategoryID], [sup].[SupplierID]
FROM [Products] AS [prod]
INNER JOIN [Categories] AS [cat] ON [prod].[CategoryID] = [cat].[CategoryID]
INNER JOIN [Suppliers] AS [sup] ON [prod].[SupplierID] = [sup].[SupplierID]
ORDER BY (SELECT 1)
OFFSET #__p_1 ROWS FETCH NEXT #__p_2 ROWS ONLY',N'#__p_1 int,#__p_2 int',#__p_1=0,#__p_2=10
I'm seeing a lot of people doing linq order by using dynamic parameter but all of them use lambda not query expression, please enlighten me
As was already mentioned, you are passing a string value instead of an expression that reflects the column name. There are options for what you want however, see for example here.

LINQ from objects Left Join

I have a linq query that works fine when I join two tables, but when I include another table, it does not return data. Please help me figure out what I am doing wrong.
First Linq returns data:
var q = (from c in _context.Complaint
join cl in _context.Checklist on c.COMP_ID equals cl.COMP_ID into clleft
from cls in clleft.DefaultIfEmpty()
orderby c.timestamp descending
select new
{
FileNum = c.FileNum
}).AsQueryable().Distinct();
return q;
When I add this table, no data returns
var q = (from c in _context.Complaint
join cl in _context.Checklist on c.COMP_ID equals cl.COMP_ID into clleft
from cls in clleft.DefaultIfEmpty()
join oim in _context.OIM_EMPLOYEE on cls.MonitorEnteredEmpID equals oim.EmpID into oimleft
from oims in oimleft.DefaultIfEmpty()
orderby c.timestamp descending
select new
{FileNum = c.FileNum
}).AsQueryable().Distinct();
return q;

Doctrine Datetime and where condition

I am writing a Doctrine 2.3 Query and I am facing some issues:
The SQL Query which I am reflecting was:
SELECT *
FROM `entry`
WHERE `plate` LIKE '%'
AND `recognition_datetime` BETWEEN '2013-03-13 22:20:18'
AND '2013-03-13 22:20:20';
I am getting the out put with the rows selected.
Doctrine which I am trying:
Opt 1:
$qry = $this->manager()->createQueryBuilder()
->from($this->entity, 'e')
->select('e');
$qry->where('e.plate like :plate');
$qry->setParameter('plate', $plate);
$qry->add('where', "e.datetime between '2013-03-13 22:20:18' and '2013-03-13 22:20:20'");
$qry->setMaxResults( $limit );
It out puts only the first where condition:
SELECT e FROM Myproject\Domain\result e WHERE e.plate like '%'
Opt 2:
$qry = $this->manager()->createQueryBuilder()
->from($this->entity, 'e')
->select('e');
$qry->where('e.plate like :plate');
$qry->setParameter('plate', $plate);
$qry->andWhere('e.datetime BETWEEN :monday AND :sunday')
->setParameter('monday', $fromdate->format('Y-m-d H:i:s'))
->setParameter('sunday', $todate->format('Y-m-d H:i:s'));
It prints only the second where as query. Can some one help me how to write multiple where/And/or condition?
After some Research I found few thing which solved my problems:
Query Generation:
//CREATING QUERY BUILDER
$qry = $this->manager()->createQueryBuilder()
->from('YOUR_ENTITY_HERE', 'e')
->select('e');
//LIKE
$ex1 = $qry->expr()->like('e.user', "'".$user."'");
//BETWEEN
$ex2 = $qry->expr()->between('e.datetime',"'".$datetime."'","'".$dateto."'");
//IN
$ex3 = $qry->expr()->in('e.country', $country);
//ADDING ALL EXPRESSION TO ONE INBETWEEN EXPRESSION "AND" OPERATION
$Query = $qry->expr()->andX($ex1,$ex2,$ex3);
//ADDING ALL EXPRESSION TO ONE INBETWEEN EXPRESSION "OR" OPERATION
$Query = $qry->expr()->orX($ex1,$ex2,$ex3);
//ADDING TOTAL EXPRESSIONS TO WHERE
$qry->where($Query);
//GENERATE QUERY
$qry->getQuery();
//FINAL OPERATIONS
//EXECUTE
$qry->execute();
//GET ARRAY OUT PUT
$qry->getArrayResult();
//GET DB OBJECT
$qry->getResult();
Other Methods for Providing IN Operations:
OTHER WAY TO USE IN OPERATION:
$country=array('Us','UK','IND','BE');
$exp = $this->manager()->getExpressionBuilder();
$qry = $this->manager()->createQueryBuilder()
->select('e')
->from('YOUR_ENTITY_HERE', 'e')
->add('where', $exp->in('e.country', $country));

How to get the item count for sub-categories on each parent?

This is related to the following post:
The function that retrieves the item counts for each folder (category) is:
ALTER FUNCTION [dbo].[GetFolderReceiptCount]
(
-- Add the parameters for the function here
#FolderID bigint
)
RETURNS int
AS
BEGIN
DECLARE #Return int
SET #Return = 0
SELECT
--H.ReceiptFolderID,
#Return = COUNT(H.ReceiptFolderID)
FROM
tbl_ReceiptFolderLnk H
JOIN tbl_Receipt D ON H.ReceiptID = D.ReceiptID
WHERE ReceiptFolderID=#FolderID
GROUP BY
H.ReceiptFolderID
-- Return the result of the function
RETURN #Return
END
How can this be altered to return counts for each parent?
You should change the function to return a table variable, or use a stored procedure so that you can get a data set
The SQL Statement should be similar to this:
SELECT
H.ReceiptFolderID, COUNT(H.ReceiptFolderID)
FROM
tbl_ReceiptFolderLnk H
JOIN tbl_Receipt D ON H.ReceiptID = D.ReceiptID
WHERE ReceiptFolderID=#FolderID
GROUP BY
H.ReceiptFolderID