Ordinary query to Zend format Query? - zend-framework

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');

Related

How can I update a table using the following CROSS APPLY?

UPDATE ItemDim_DEV
set ActiveFlag = 0,
EndUTCDate = GETUTCDATE()
from (select i.SKU, i.itemname, i.category, i.CategoryInternalId, i.itemtype, i.IsActive, i.assetaccount, i.InternalId,
ni.sku,
ni.itemname,
ni.class_name,
ni.productclass,
ni.ItemType,
ni.isactive,
ni.assetaccount,
i.CalculatedHash, ni.hashid
from (
SELECT i.*
FROM itemDim_Dev i
WHERE i.SourceSystem = 'NetSuite'
--and InternalId = '1692'
) i
CROSS APPLY (
SELECT (CONVERT([binary](64),hashbytes('SHA2_512',
concat (ISNULL(im.TargetSKU, ni.sku), ni.itemname, pc.class_name, ni.productclass, ni.ItemType,
CAST(CASE WHEN ni.IsInactive = 'T' THEN 0 ELSE 1 END AS BIT ), ni.assetaccount)))) hashid,
ISNULL(im.TargetSKU, ni.sku) sku,
ni.itemname,
pc.class_name,
ni.productclass,
ni.ItemType,
CAST(CASE WHEN ni.IsInactive = 'T' THEN 0 ELSE 1 END AS BIT ) isactive, ni.assetaccount
FROM NetSuiteInventory ni
INNER JOIN Product_Class pc ON ni.productclass = pc.class_id
LEFT JOIN ItemMapping im ON ni.sku = im.SourceSKU
WHERE ni.ItemInternalId = CAST(i.InternalId as bigint)
and
(CONVERT([binary](64),hashbytes('SHA2_512',
concat (ISNULL(im.TargetSKU, ni.sku), ni.itemname, pc.class_name, ni.productclass, ni.ItemType,
CAST(CASE WHEN ni.IsInactive = 'T' THEN 0 ELSE 1 END AS BIT ), ni.assetaccount)))) = i.CalculatedHash
) ni
I understand that I can put a select after the from of the update but in the CROSS APPLY that is in the query starts with a select as in the second one, can you help me please.
Make a join to the target table
UPDATE A
SET XXX = YYY
FROM ItemDim_DEV A
JOIN (
--huge SELECT that I recommend you try to shorten in the next questions
CROSS APPLY (any secrets...)
) B ON A.PK = B.PK

PostgreSQL: how to convert "PIVOT" from T-SQL to PLPGSQL procedure

I would like to convert a stored procedure from T-SQL to PL/PGSQL.
Here is the T-SQL code
SELECT NO_PTF, coalesce(1, 0) as RISK_1, coalesce(2, 0) as RISK_2, coalesce(3, 0) as RISK_3, coalesce(4, 0) as RISK_4
FROM (
SELECT D.NO_PTF, C.NB_DEG_RSQ, D.MT_DEM/100 as MT_DEM
FROM public.TB_Demande D
INNER JOIN
public.TB_Compartiment C ON D.ID_CPA = C.ID_CPA
AND D.MC_UTL = 'F3000'
AND C.IN_ACT = true
) Q
PIVOT (SUM(Q.MT_DEM) FOR Q.NB_DEG_RSQ IN (1, 2, 3, 4)) as PVT
)
I tried to replace PIVOT by crosstab. But i have an error. Here is my PL/PGSQL code
SELECT NO_PTF, coalesce(1, 0) as RISK_1, coalesce(2, 0) as RISK_2, coalesce(3, 0) as RISK_3, coalesce(4, 0) as RISK_4
FROM (
SELECT D.NO_PTF, C.NB_DEG_RSQ, D.MT_DEM/100 as MT_DEM
FROM public.TB_Demande D
INNER JOIN
public.TB_Compartiment C ON D.ID_CPA = C.ID_CPA
AND D.MC_UTL = 'F3000'
AND C.IN_ACT = true
) Q
crosstab (SUM(Q.MT_DEM) FOR Q.NB_DEG_RSQ IN (1, 2, 3, 4)) as PVT
Someone have an idea about the rigth way to use crosstab here?
I am not entirely sure I understand the PIVOT syntax, but typically this is way easier in Postgres using a filtered aggregation, not the somewhat clumsy crosstab() function.
I think this should be equivalent:
select no_ptf,
sum(mt_dem) filter (where NB_DEG_RSQ = 1) as risk_1,
sum(mt_dem) filter (where NB_DEG_RSQ = 2) as risk_2,
sum(mt_dem) filter (where NB_DEG_RSQ = 3) as risk_3,
sum(mt_dem) filter (where NB_DEG_RSQ = 4) as risk_4
from (
SELECT D.NO_PTF, C.NB_DEG_RSQ, D.MT_DEM/100 as MT_DEM
FROM public.TB_Demande D
INNER JOIN public.TB_Compartiment C
ON D.ID_CPA = C.ID_CPA
AND D.MC_UTL = 'F3000'
AND C.IN_ACT = true
)
GROUP BY no_ptf;

PostgreSQL - CTE slowing the query

I have a concern regarding the use of multiple WITH clauses in a query because
in some condition, it is slowing down the performance of the query like the below example,
So first WITH clause taking the 0.345 sec to fetch the 98948 records and second WITH clause taking the 13 sec to fetch the 68199 records even its less record as compare to first one so the only difference is that we have used the aggregate function in the second WITH clause to calculate the sum of charges.
Can anybody please help us to understand why the second query taking too much time.
1.This clause taking the 0.318 sec to fetch the 98948 record,
WITH delinquency_lease_details AS (
SELECT
dp.cid,
dp.id AS delinquency_policy_id,
p.id,
dp.threshold_amount,
dp.small_balance_amount,
dp.delinquency_threshold_type_id,
cl.id,
cl.primary_customer_id AS customer_id,
cl.lease_status_type_id,
cl.occupancy_type_id,
COALESCE( cl.building_name || ' - ' || cl.unit_number_cache, cl.building_name, cl.unit_number_cache ) AS unit_number, func_format_customer_name ( cl.name_first, cl.name_last, cl.company_name ) customer_name, cl.property_name, TZ.time_zone_name AS property_timezone
FROM
cached_leases cl
JOIN lease_details ld ON ( ld.cid = cl.cid AND ld.lease_id = cl.id )
JOIN delinquency_policies dp ON ( dp.cid = ld.cid AND ld.delinquency_policy_id = dp.id )
JOIN properties p ON ( p.cid = lp.cid AND p.id = lp.property_id )
JOIN time_zones TZ ON ( TZ.id = p.time_zone_id )
WHERE
cl.cid = 1111
AND cl.lease_status_type_id IN ( 4, 5 )
AND cl.occupancy_type_id IN ( 1, 2, 3, 4, 6, 9, 10, 11 )
AND cl.termination_list_type_id IS NULL
)
SELECT * FROM delinquency_lease_details;
2. This clause taking the 13 sec to fetch the 68199 records and if I just run the query without WITH clause then it is taking 0.564 seconds,
WITH delinquent_balance AS (
SELECT
dld.cid,
dld.id,
min( c.post_date ) AS min_post_date,
sum( c.transaction_amount_due ) AS delinquent_amount
FROM
cached_leases dld
JOIN charges at ON ( at.cid = dld.cid AND at.lease_id = dld.id AND c.is_temporary = FALSE AND c.is_deleted = FALSE )
JOIN charge_codes cc ON ( c.ar_code_id = cc.id AND c.cid = cc.cid AND cc.ledger_filter_id = 27 )
WHERE
dld.cid = 1111
AND ( ( c.transaction_amount_due > 0 AND c.post_date < CURRENT_DATE ) OR c.transaction_amount_due < 0 )
AND NOT EXISTS (
select
1
from
repayment_charges
WHERE
cid = c.cid
AND property_id = c.property_id
AND charge_id = c.id
AND is_active = true
)
GROUP BY
dld.cid,
dld.id
) select * from delinquent_balance;
As per this link, the WITH clause is the optimization barrier for Postgres database so it's really a cause then what we should use in place of WITH clause for complex queries because I have used the 10 WITH clauses in query and it is slowing down the performance of the query but out of that I have given two clauses only to get the some conclusion because the second clause taking more time as compared to another one.

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

Why doesn't work ADate between #Startdate and #Enddate?

I have a query like this:
SELECT #Amount = SUM(T.Amount) FROM (
SELECT
(
SELECT DISTINCT SUM(X.Price)
FROM X
WHERE X.ID = Y.XID OR X.ID = Z.XID
AND (X.ADate BETWEEN #StartDate AND #EndDate)
) AS Amount
FROM B
LEFT JOIN Y ON B.YId = Y.Id
LEFT JOIN Z ON B.ZId = Z.Id
WHERE B.Id = #Id
AND (B.YId = #YId OR #YId < 0)
AND (B.ZId = #ZId OR #ZId < 0)) AS T
And which start and end date I choose. The result is the same.
By example a start date 1/1/2012 and a end date 1/31/2012
and then a selection of a start date 1/1/2014 and a end date 1/31/2014
by the following data: Price 500 and a ADate = 1/24/2012
Both results are 500?!
What do I wrong?
I've tried to:
AND (X.ADate BETWEEN CAST(#StartDate AS DATETIME) AND CAST(#EndDate AS DATETIME))
Sleeping is good. The problem was => ( and ) was missing.
Solvation: WHERE (X.ID = Y.XID OR X.ID = Z.XID)