Use LIMIT and OFFSET with doctrines addSelect? - doctrine

I have following code:
->createQueryBuilder()
->select("c.id, c.address, c.name")
->addSelect('(SELECT o.name FROM OOHMediaBundle:Offer o WHERE p.contractor_id = c.id ORDER BY o.created_at DESC LIMIT 1 OFFSET 0) as offer1')
->addSelect('(SELECT o.name FROM OOHMediaBundle:Offer o WHERE p.contractor_id = c.id ORDER BY o.created_at DESC LIMIT 1 OFFSET 1) as offer2')
It obviously do not work as LIMIT and OFFSET are not supported. Docs list solution for limiting main query. However I need to limit those subqueries and not main query.
So how to limit those subqueries?

Related

Percentile_Cont function throwing error

I have this query where I am trying to introduce a non-static value into PERCENTILE_CONT:
SELECT perf2.REVIEW_PERIOD
, PERCENTILE_CONT(goalsASP.GOAL*.01) WITHIN GROUP (ORDER BY AVG_AMT ASC) ast75
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD
The error thrown is:
ORA-30497: Argument should be a constant or a function of expressions in GROUP BY.
30497. 00000 - "Argument should be a constant or a function of expressions in GROUP BY."
This is in a view, it was working fine when goalsASP.GOAL*.01 was .75 and I have a stored procedure where feeding a column as an argument works just fine so I'm kind of at a loss for what I'm doing wrong here.
Got it. It's not so much a problem of Percentile_Cont, it's a problem of correct grouping.
To troubleshoot I isolated goalsASP.GOAL
SELECT perf2.REVIEW_PERIOD
, goalsASP.GOAL
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD
Then it became obvious that I needed to also group by goalsASP.GOAL.
So, then, the answer is:
SELECT perf2.REVIEW_PERIOD
, PERCENTILE_CONT(goalsASP.GOAL*.01) WITHIN GROUP (ORDER BY AVG_AMT ASC) ast75
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD,
goalsASP.GOAL
Kind of embarrassing that I didn't see that before, but tired eyes miss this stuff.

Conversion of Oracle query to teradata query

How to convert this below query to equivalent teradate query. I tried but results varies a lot.
select il.domainN as listname, il.SourceID, ns.sourcename, cbo.customerid, cu.username, hv.domainN as HTname
, nvl((select 1
from mydb.customerPP cpp
where cbo.customerid = cpp.customerid
and NOT EXISTS (select 1 from mydb.customerPI cpt where cpp.customerid = cpt.customerid)
and trunc(cpp.startdate) <= sysdate
group by cpp.customerid),0) as BBID
from mydb.customerBO cbo
join mydb.customers cu on cbo.customerid = cu.customerid
join mydb.inv il on cbo.domainN = il.domainN
join mydb.Sources ns on il.SourceID = ns.SourceID
left join mydb2.HT hv on (il.domainN = hv.domainN
and hv.sDate+1 >= il.dDate
and il.dDate+1 >= hv.sDate)
where cbo.customerBOID = 1
and cu.statusid = 1
and il.sourceTID = 2
and il.joinbydate >= cbo.cDate
and trunc(il.dDate) = trunc(sysdate)
Thanks.
Use coalesce instead nvl and compare explain statements to see whether you have left outer joins converted to inner joins for nvl on Teradata.

how to pass select subquery in where clause using laravel

This is my SQl query
select sum(stock.total_in_stock) as total_in_stock
,stock.name
,stock.inventory_id
from (
select i.store_id
,i.model_id
,i. total_in_stock
,i.id as inventory_id
, m.*
from `inventory` as `i`
left join `model_store` as `ms` on `ms`.`store_id` = `i`.`store_id`
left join `model` as `m` on `m`.`id` = `ms`.`model_id`
where `i`.`model_id` = m.id
and `m`.`status` = 1
and `ms`.`status` = 1
and `i`.`created_at` = (
select si.created_at
from inventory AS si
where si.model_id = i.model_id
and si.store_id = i.store_id
and si.status=1
order by si.created_at desc limit 1
)
) as stock
group by stock.model_id
In laravel, it is written as this:
$results1 = DB::table('inventory as i')
->select(DB::raw( 'sum(stock.total_in_stock) as total_in_stock,stock.name,stock.inventory_id FROM ( SELECT i.store_id,i.model_id,i. total_in_stock,i.id as inventory_id, m.* '))
->leftJoin('model_store as ms','ms.store_id','=','i.store_id')
->leftJoin('model as m','m.id','=','ms.model_id')
->where('i.model_id','=', 'm.id')
->where('m.status','=', '1')
->where('ms.status','=', '1')
->where("i.created_at","=",function($query) {
$query->select(DB::raw("si.created_at FROM inventory AS si WHERE si.model_id = i.model_id AND si.store_id = i.store_id AND si.status=1 ORDER BY si.created_at DESC LIMIT 1)) as stock GROUP BY stock.model_id"));
});
It gives me the following error:-
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 (SQL: select sum(stock.total_in_stock) as total_in_stock,stock.name,stock.inventory_id FROM ( SELECT i.store_id,i.model_id,i. total_in_stock,i.id as inventory_id, m.* from `inventory` as `i` left join `model_store` as `ms` on `ms`.`store_id` = `i`.`store_id` left join `model` as `m` on `m`.`id` = `ms`.`model_id` where `i`.`model_id` = m.id and `m`.`status` = 1 and `ms`.`status` = 1 and `i`.`created_at` = (select si.created_at FROM inventory AS si WHERE si.model_id = i.model_id AND si.store_id = i.store_id AND si.status=1 ORDER BY si.created_at DESC LIMIT 1 )) as stock GROUP BY stock.model_id))
It takes 2 closing brackets at the end and gives the above error. Please help me writing the above SQL query in laravel.
Answering your question that's in the tile: the subquery where needs fix:
->where("i.created_at", function($query) {
$query->from('inventory as si')
->selectRaw('max(si.created_at)')
->whereRaw('si.model_id = i.model_id AND ...');
});
However, in order to create a subquery in the from clause, you need to pass raw query, so your whole code requires a bit of toSql() and setBindings(...), which is cumbersome.
So to get the answer to your problem, better describe the problem itself instead.

Counting the total number of rows depending on a column value

I have a query that should count the total number of rows returned depending on a column value. For example:
As you can see, the M field should display the total number of rows returned which should be 5 because the FT_LOT are all the same value. Here is the query that I have so far:
SELECT DISTINCT
VBATCH_ID, MAXIM_PN, BAGNUMBER, FT_LOT
, m
, level as n
FROM
(
SELECT
VBATCH_ID, MAXIM_PN, BAGNUMBER, FT_LOT, QTY, DC, PRINTDATE, WS_GREEN, WS_PNR, WS_PCN, MSL, BAKETIME, EXPTIME
, una
, dulo
, (dulo - una) + 1 AS m
FROM
(
SELECT c.containername VBATCH_ID
,pb.productname MAXIM_PN
,bn.wipdatavalue BAGNUMBER
,ln.wipdatavalue FT_LOT
,aw.wipdatavalue QTY
,DECODE(ln.wipdatavalue,la.attr_081,la.attr_083
,la.attr_085,la.attr_087
,la.attr_089,la.attr_091
,la.attr_093,la.attr_095
,la.attr_097,la.attr_099
,la.attr_101,la.attr_103
,la.attr_105,la.attr_107
,la.attr_109,la.attr_111
,la.attr_113,la.attr_116
,la.attr_117,la.attr_119
) DC
,TO_CHAR(SYSDATE,'MM/DD/YYYY HH:MI:SS PM') PRINTDATE
,DECODE(UPPER(la.attr_158),'GREEN','HF',NULL) WS_GREEN
,DECODE(la.attr_140,NULL,NULL,'PNR') WS_PNR
,DECODE(la.Attr_080,NULL,NULL,'PCN') WS_PCN
,p.attr_011 MSL
,P.attr_013 BAKETIME
,p.attr_014 EXPTIME
, CASE
WHEN INSTR(bn.wipdatavalue, '-') = 0 THEN
bn.wipdatavalue
ELSE
SUBSTR(bn.wipdatavalue, 1, INSTR(bn.wipdatavalue, '-')-1)
END AS una
, CASE
WHEN INSTR(bn.wipdatavalue, '-') = 0 THEN
bn.wipdatavalue
ELSE
SUBSTR(bn.wipdatavalue, INSTR(bn.wipdatavalue, '-') + 1)
END AS dulo
FROM Container C
JOIN a_lotattributes la ON c.lotattributesid = la.lotattributesid
JOIN product p ON c.productid=p.productid
JOIN productbase pb ON p.productbaseid=pb.productbaseid
JOIN a_adhocwipdatarecord a ON a.objectrefid=c.containerid
JOIN a_adhocwipdatarecorddetails bn ON a.adhocwipdatarecordid=bn.adhocwipdatarecordid AND bn.wipdatanamename ='TR_BAG_NUMBER'
LEFT JOIN a_adhocwipdatarecorddetails ln ON a.adhocwipdatarecordid=ln.adhocwipdatarecordid AND ln.wipdatanamename ='TR_FT_LOT NUMBER'
LEFT JOIN a_adhocwipdatarecorddetails aw ON A.adhocwipdatarecordid=aw.adhocwipdatarecordid AND aw.wipdatanamename ='TR_FT LOT QTY'
WHERE ln.wipdatavalue = :ftlot AND bn.wipdatavalue LIKE :wip
)
) WHERE level LIKE :n
CONNECT BY LEVEL <= m
ORDER BY BAGNUMBER
Thanks for helping out guys.
Actually GROUP BY is not the solution. Having looked again at your desired output I have realised that what you want is an analytic count.
Your posted query is a bit of a mess and, sorry ,but I'm not prepared to invest time in it. This is the sort of structure you need:
select vbatch_id, maxim_pn, bagnumber, ft_lot
, count(*) over (partition by ft_lot) m
from whatever ...
Find out more.
Not sure why you need the DISTINCT. DISTINCT almost always indicates a failure to get the WHERE clause right.

Query that uses Clustered Index Scan instead of seek

I have the following query that returns < 300 results. It is currently taking about 4 seconds to complete, and when I look at the execution plan, it shows that it is spending 41% of resources on a clustered index scan. My limited knowledge of database administration suggests that a clustered index seek would improve performance. How can I get the query to use a clustered index seek instead of a clustered index scan? Below is the pertinent information and the query.
Sql Server 2008 R2
Table PMDME approx 140,000 rows (this is the one that is taking up 41% of resources)
Server Hardware: 16 core 2.7gz processors, 48gb ram
DECLARE #start date, #end date
SET #start = '2013-01-01'
SET #end = CAST(GETDATE() AS DATE)
SELECT
b.total,
c.intakes,
d.ships,
a.CODE_,
RTRIM(a.NAME_) as name,
f.employee as Salesperson,
g.referral_type_id,
h.referral_type,
e.slscode,
a.city,
a.STATE_,
a.zip
FROM PACWARE.ADS.RFDME a
LEFT OUTER JOIN (
SELECT SUM(b.quantity) total, a.ref_id from event.dbo.sample a
JOIN event.dbo.sample_parts b on a.id = b.sample_id
JOIN PACWARE.ADS.PTDME c on b.part_id = c.CODE_
WHERE c.MEDICAREID = 'E0607' AND a.order_date between #start and #end
GROUP BY a.ref_id
)b on a.CODE_ = b.ref_id
LEFT OUTER JOIN (
SELECT COUNT(a.CODE_)as intakes, rfcode
FROM PACWARE.ADS.PMDME a
WHERE a.REGDATETIME BETWEEN #start and #end
GROUP BY a.RFCODE
) c on a.CODE_ = c.rfcode
LEFT OUTER JOIN (
SELECT
COUNT(a.CODE) as ships, b.rfcode
FROM
(
SELECT
A.ACCOUNT AS CODE,
MIN(CAST(A.BILLDATETIME AS DATE)) AS SHIPDATE
FROM PACWARE.ADS.ARODME A
LEFT OUTER JOIN PACWARE.ADS.PTDME B ON A.PTCODE=B.CODE_
LEFT OUTER JOIN event.dbo.newdate() D ON A.ACCOUNT=D.ACCOUNT
LEFT OUTER JOIN event.dbo.newdate_extras() D2 ON A.ACCOUNT=D2.ACCOUNT
WHERE A.BILLDATETIME>=#start
AND A.BILLDATETIME=#start AND D.NEWDATE=#start AND D2.NEWDATE'ID'
Group by
A.ACCOUNT,
B.MEDICAREID,
A.CATEGORY
) a
JOIN PACWARE.ADS.PMDME b on a.CODE = b.CODE_
GROUP BY b.RFCODE
) d on a.CODE_ = d.rfcode
LEFT OUTER JOIN event.dbo.employee_slscode e on a.SLSCODE = e.slscode
JOIN event.dbo.employee f on e.employee_id = f.id
JOIN event.dbo.referral_data g on a.CODE_ = g.CODE_
JOIN event.dbo.referral_type h on g.referral_type_id = h.id
WHERE total > 0
I would try creating first and index just for the colum REGDATETIME on PACWARE.ADS.PMDME table.
GO
CREATE NONCLUSTERED INDEX [IX_PMDME_REGDATETIME] ON PACWARE.ADS.PMDME
(
[REGDATETIME] ASC
)
GO
Test how it works. I would also test adding another index to the column RFCODE (same table) if the selectivity of the column is good enough.

Resources