Changing stored procedure - sql

I have a proc that print checks if there is any new checks to be print. If there is nothing to issue new checks it wont print any. Now i want to modify this proc like even if i don't have any new checks to be print, it should pick up at least one check to be print.( even if it is already printed). Can you tell me how to do that. Here is the stored proc.
CREATE PROCEDURE [proc_1250_SELCashiersChecksForPrint] AS
SELECT t_DATA_CashiersChecksIssued.ControlNbr,
t_DATA_CashiersChecksIssued.Audit_DateAdded,
t_DATA_CashiersChecksIssued.BatchNbr,
t_DATA_CashiersChecksIssued.SerialNbr,
t_DATA_CashiersChecksIssued.CheckRTN,
t_DATA_CashiersChecksIssued.CheckAccountNbr,
t_DATA_CashiersChecksIssued.Amount,
t_DATA_CashiersChecksIssued.DateIssued,
t_DATA_CashiersChecksIssued.Payee,
t_DATA_CashiersChecksIssued.Address,
t_DATA_CashiersChecksIssued.City,
t_DATA_CashiersChecksIssued.State,
t_DATA_CashiersChecksIssued.Zip,
t_DATA_Reclamation.ClaimId,
t_DATA_Reclamation.NoticeDate,
t_DATA_Reclamation.FirstName,
t_DATA_Reclamation.MiddleName,
t_DATA_Reclamation.LastName,
t_DATA_Reclamation.ClaimTotal,
t_PCD_Claimant.Name AS Agency,
t_DATA_CashiersChecksIssued.IDENTITYCOL
FROM t_DATA_CashiersChecksIssued INNER JOIN
t_DATA_Reclamation ON
t_DATA_CashiersChecksIssued.ControlNbr = t_DATA_Reclamation.ControlNbr
INNER JOIN
t_PCD_Claimant ON
t_DATA_Reclamation.ClaimantCode = t_PCD_Claimant.ClaimantCode
WHERE (t_DATA_CashiersChecksIssued.SerialNbr IS NULL) AND
(t_DATA_CashiersChecksIssued.DateIssued IS NULL)
ORDER BY t_DATA_CashiersChecksIssued.Audit_DateAdded ASC,
t_DATA_CashiersChecksIssued.ControlNbr ASC
Let me know if you need more information.

SELECT TOP 1 t_DATA_CashiersChecksIssued.ControlNbr,
t_DATA_CashiersChecksIssued.Audit_DateAdded,
t_DATA_CashiersChecksIssued.BatchNbr,
t_DATA_CashiersChecksIssued.SerialNbr,
t_DATA_CashiersChecksIssued.CheckRTN,
t_DATA_CashiersChecksIssued.CheckAccountNbr,
t_DATA_CashiersChecksIssued.Amount,
t_DATA_CashiersChecksIssued.DateIssued,
t_DATA_CashiersChecksIssued.Payee, t_DATA_CashiersChecksIssued.Address,
t_DATA_CashiersChecksIssued.City, t_DATA_CashiersChecksIssued.State,
t_DATA_CashiersChecksIssued.Zip, t_DATA_Reclamation.ClaimId,
t_DATA_Reclamation.NoticeDate, t_DATA_Reclamation.FirstName,
t_DATA_Reclamation.MiddleName, t_DATA_Reclamation.LastName,
t_DATA_Reclamation.ClaimTotal, t_PCD_Claimant.Name AS Agency,
t_DATA_CashiersChecksIssued.IDENTITYCOL
FROM t_DATA_CashiersChecksIssued
INNER JOIN t_DATA_Reclamation ON t_DATA_CashiersChecksIssued.ControlNbr = t_DATA_Reclamation.ControlNbr
INNER JOIN t_PCD_Claimant ON t_DATA_Reclamation.ClaimantCode = t_PCD_Claimant.ClaimantCode
ORDER BY t_DATA_CashiersChecksIssued.Audit_DateAdded DESC

Use the TOP n SQL syntax :
if EXISTS ( /* Look for an unprinted check - "date_issued is null" */ )
/* print unprinted checks */
ELSE
select top 1 /* already-printed-checks */
where .... "date_issued is not null"
OR
Do you want to print a "Voided/Cancelled" check - when you do that?

You have to decide how you want to pick your "at least one".
The simplest way (probably) is to remove whatever condition in the WHERE clause is excluding already printed checks. Let's assume that's t_DATA_CashiersChecksIssued.DateIssued IS NULL. Now add a column to your SELECT clause like this: CASE WHEN t_DATA_CashiersChecksIssued.DateIssued IS NULL then 0 ELSE 1 END and make that column first in your ORDER BY clause.
Now in the procedure, fetch just one row from this cursor. If this new column has the value 0, there's at least one new check to be processed and you should iterate through the cursor but stop when you get to an already issued one. If it has the value 1, there are no new checks.
Edit: The other approach would be to do it right in your SQL. Leave the original as is, but add a clause like:
UNION ALL SELECT ... AND ROWNUM = 1 where ... represents your existing query, but with the condition to exclude already printed checks removed. On second thought, this may be simpler.

Related

How to exclude SQL variable in output

I have a complex SQL query where I have a few cases that use END AS variableName. I then use variableName to do some logic and then create a new variable which I want in the output result. However when I run the query, all the END AS variableNames that I have used are also outputted in the results.
Is there a way that I can exclude these variables as I only want the final variable that uses these variableNames.
Thanks
EDIT, here is a query explaining my problem
SELECT DISTINCT
mt.src_id AS “SRC_ID”,
CASE
WHEN mt.cd = ‘TAN’ THEN
(
(
SELECT SUM(src_amt)
FROM source_table st
WHERE mt.id = st.id
AND st._cd = ‘TAN’
AND st.amt_cd = ‘ABL’)
)
END AS src_amt
FROM MAIN_TABLE mt
WHERE
mf.dt >= 2021-12-12
AND SRC_AMT > 10
I need SRC_AMT to be used as some sort of logic but when I run the query, it prints out in the output as it's own column. I want to ignore this variable
you can wrap the whole thing into a new select-statement:
select SRC_ID from ( <entire previous query here> )

How to write an Open SQL statement with substring in the JOIN ON condition? [duplicate]

I have the following select statement in ABAP:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
INTO corresponding fields of table GT_INSTMUNIC_F
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN EVER AS EV on
MUNIC~POD = EV~VREFER(9).
"where EV~BSTATUS = '14' or EV~BSTATUS = '32'.
My problem with the above statement is that does not recognize the substring/offset operation on the 'ON' clause. If i remove the '(9) then
it recognizes the field, otherwise it gives error:
Field ev~refer is unknown. It is neither in one of the specified tables
nor defined by a "DATA" statement. I have also tried doing something similar in the 'Where' clause, receiving a similar error:
LOOP AT gt_instmunic.
clear wa_gt_instmunic_f.
wa_gt_instmunic_f-mandt = gt_instmunic-mandt.
wa_gt_instmunic_f-bis = gt_instmunic-bis.
wa_gt_instmunic_f-ab = gt_instmunic-ab.
wa_gt_instmunic_f-zzelecdate = gt_instmunic-zzelecdate.
wa_gt_instmunic_f-ZZCERTDATE = gt_instmunic-ZZCERTDATE.
wa_gt_instmunic_f-CONSYEAR = gt_instmunic-CONSYEAR.
wa_gt_instmunic_f-ZDIMO = gt_instmunic-ZDIMO.
wa_gt_instmunic_f-ZZONE_M = gt_instmunic-ZZONE_M.
wa_gt_instmunic_f-ZZONE_T = gt_instmunic-ZZONE_T.
wa_gt_instmunic_f-USAGE_M = gt_instmunic-USAGE_M.
wa_gt_instmunic_f-USAGE_T = gt_instmunic-USAGE_T.
temp_pod = gt_instmunic-pod.
SELECT vrefer
FROM ever
INTO wa_gt_instmunic_f-vrefer
WHERE ( vrefer(9) LIKE temp_pod ). " PROBLEM WITH SUBSTRING
"AND ( BSTATUS = '14' OR BSTATUS = '32' ).
ENDSELECT.
WRITE: / sy-dbcnt.
WRITE: / 'wa is: ', wa_gt_instmunic_f.
WRITE: / 'wa-ever is: ', wa_gt_instmunic_f-vrefer.
APPEND wa_gt_instmunic_f TO gt_instmunic_f.
WRITE: / wa_gt_instmunic_f-vrefer.
ENDLOOP.
itab_size = lines( gt_instmunic_f ).
WRITE: / 'Internal table populated with', itab_size, ' lines'.
The basic task i want to implement is to modify a specific field on one table,
pulling values from another. They have a common field ( pod = vrefer(9) ). Thanks in advance for your time.
If you are on a late enough NetWeaver version, it works on 7.51, you can use the OpenSQL function LEFT or SUBSTRING. Your query would look something like:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN ever AS ev
ON MUNIC~POD EQ LEFT( EV~VREFER, 9 )
INTO corresponding fields of table GT_INSTMUNIC_F.
Note that the INTO clause needs to move to the end of the command as well.
field(9) is a subset operation that is processed by the ABAP environment and can not be translated into a database-level SQL statement (at least not at the moment, but I'd be surprised if it ever will be). Your best bet is either to select the datasets separately and merge them manually (if both are approximately equally large) or pre-select one and use a FAE/IN clause.
They have a common field ( pod = vrefer(9) )
This is a wrong assumption, because they both are not fields, but a field an other thing.
If you really need to do that task through SQL, I'll suggest you to check native SQL sentences like SUBSTRING and check if you can manage to use them within an EXEC_SQL or (better) the CL_SQL* classes.

Set a Variable in a case expression

I am looking to pass declared variables to build my string. I think I want to set my variable via a case expression but I have not done this before. Here is what I have done thus far.
DECLARE #stu_conv AS VARCHAR(5)
-- I think I need a select here.
set #stu_conv = CASE WHEN ITMMASTER.STU_0 ='KG' THEN'2.2'END
SELECT
YPRIMAT.YCROPYR_0
,ITMMASTER.TCLCOD_0
,SPRICLIST.DCGVAL_3
,ITMMASTER.TSICOD_2
,ITMMASTER.ACCCOD_0
,(BASPRI_0*#stu_conv) AS ImportstringAS Importstring
FROM LIVE.YPRIMAT
INNER JOIN LIVE.ITMMASTER ON YPRIMAT.ITMREF_0 = ITMMASTER.ITMREF_0
LEFT OUTER JOIN LIVE.SPRICLIST ON ITMMASTER.TCLCOD_0 = SPRICLIST.PLICRI1_0
WHERE SPRICLIST.PLICRD_0 = 'SPL000020'
I don't see the point for using a variable here, and trying to set it outside the query does not make sense, since you most likely want the value to reset for each row.
I would suggest moving the case expression into the query, as follows:
select
y.ycropyr_0,
i.tclcod_0,
s.dcgval_3,
i.tsicod_2,
i.acccod_0,
baspri_0 * case when i.stu_0 = 'KG' then 2.2 else 1 end as importstringas importstring
from live.yprimat y
inner join live.itmmaster i on y.itmref_0 = i.itmref_0
left outer join live.spriclist s on i.tclcod_0 = s.plicri1_0
where s.plicrd_0 = 'SPL000020'
I assumed that you want a value of 1 when stu_0 is not 'KG', but you can change this as needed.
Side note:
I modified your query to use table aliases. This makes the query shorter to write and somehow easier to read
you would need to prefix column baspri_0 with the table it belongs to (as your query is, it is not possible to tell)
I'm not sure why you're declaring a string and then multiplying it, but I would just inline the case (and add a default case?):
,(BASPRI_0 * CASE
WHEN ITMMASTER.STU_0 ='KG'
THEN 2.2
ELSE ???
END) AS Importstring

Syntax error on WITH clause

I am working on a web app and there are some long winded stored procedures and just trying to figure something out, I have extracted this part of the stored proc, but cant get it to work. The guy who did this is creating alias after alias.. and I just want to get a section to work it out. Its complaining about the ending but all the curly brackets seem to match. Thanks in advance..
FInputs is another stored procedure.. the whole thing is referred to as BASE.. the result of this was being put in a temp table where its all referred to as U. I am trying to break it down into separate sections.
;WITH Base AS
(
SELECT
*
FROM F_Inputs(1,1,100021)
),
U AS
(
SELECT
ISNULL(q.CoverPK,r.CoverPK) AS CoverPK,
OneLine,
InputPK,
ISNULL(q.InputName,r.InputName) AS InputName,
InputOrdinal,
InputType,
ParentPK,
InputTriggerFK,
ISNULL(q.InputString,r.InputString) AS InputString,
PageNo,
r.RatePK,
RateName,
Rate,
Threshold,
ISNULL(q.Excess,r.Excess) AS Excess,
RateLabel,
RateTip,
Refer,
DivBy,
RateOrdinal,
RateBW,
ngRequired,
ISNULL(q.RateValue,r.RateValue) AS RateValue,
ngClass,
ngPattern,
UnitType,
TableChildren,
TableFirstColumn,
parentRatePK,
listRatePK,
NewParentBW,
NewChildBW,
ISNULL(q.SumInsured,0) AS SumInsured,
ISNULL(q.NoItems,0) AS NoItems,
DisplayBW,
ReturnBW,
StringBW,
r.lblSumInsured,
lblNumber,
SubRateHeading,
TrigSubHeadings,
ISNULL(q.RateTypeFK,r.RateTypeFK) AS RateTypeFK,
0 AS ListNo,
0 AS ListOrdinal,
InputSelectedPK,
InputVis,
CASE
WHEN ISNULL(NewChildBW,0) = 0
THEN 1
WHEN q.RatePK is NOT null
THEN 1
ELSE RateVis
END AS RateVis,
RateStatus,
DiscountFirstRate,
DiscountSubsequentRate,
CoverCalcFK,
TradeFilter,
ngDisabled,
RateGroup,
SectionNo
FROM BASE R
LEFT JOIN QuoteInputs Q
ON q.RatePK = r.RatePK
AND q.ListNo = 0
AND q.QuoteId = 100021 )
Well, I explained the issue in the comments section already. I'm doing it here again, so future readers find the answer more easily.
A WITH clause is part of a query. It creates a view on-the-fly, e.g.:
with toys as (select * from products where type = 'toys') select * from toys;
Without the query at the end, the statement is invalid (and would not make much sense anyhow; if one wanted a permanent view for later use, one would use CREATE VIEW instead).

SQL regex and field

I want to change the query to return multiply values in extra_fields, how can I change the regex? Also I don't understand what extra_fields is - is it a field? If so why it is not called with the table prefix like i.extra_fields?
SELECT i.*,
CASE WHEN i.modified = 0 THEN i.created ELSE i.modified END AS lastChanged,
c.name AS categoryname,
c.id AS categoryid,
c.alias AS categoryalias,
c.params AS categoryparams
FROM #__k2_items AS i
LEFT JOIN #__k2_categories AS c ON c.id = i.catid
WHERE i.published = 1
AND i.access IN(1,1)
AND i.trash = 0
AND c.published = 1
AND c.access IN(1,1)
AND c.trash = 0
AND (i.publish_up = '0000-00-00 00:00:00'
OR i.publish_up <= '2013-06-12 22:45:19'
)
AND (i.publish_down = '0000-00-00 00:00:00'
OR i.publish_down >= '2013-06-12 22:45:19'
)
AND extra_fields REGEXP BINARY '(.*{"id":"2","value":\["[^\"]*1[^\"]*","[^\"]*2[^\"]*","[^\"]*3[^\"]*"\]}.*)'
ORDER BY i.id DESC
The extra_fields is a column of the #__k2_items table. The table qualifier can be omitted, because it is not ambiguous in this query. The column is JSON encoded. That is a serialization format used to store information which is not searchable by design. Applying a RegExp may work one day, but fail another day, since there is no guarantee for id preceeding value (as in your example).
The right way
The right way to filter this is to ignore the extra_fields condition in the SQL query an evaluate in the resultset instead. Example:
$rows = $db->loadObjectList('id');
foreach ($rows as $id => $row) {
$extra_fields = json_decode($row->extra_fields);
if ($extra_fields->id != 2) {
unset($rows[$id]);
}
}
The short way
If you can't change the database layout (which is true for extensions you want to keep updateable), you must split the condition into two, because there is no guarantee for a certain order of the subfields. For some reason, one day value may occur before id. So change your query to
...
AND extra_fields LIKE '%"id":"2"%'
AND extra_fields REGEXP BINARY '"value":\[("[^\"]*[123][^\"]*",?)+\]'
Prepare an intermediate table to hold the contents of extra_fields. Each extra_fields field will be converted into a series of records. Then do a join.
Create a trigger and cronjob to keep the temp table in sync.
Another way is to write UDF in Perl that will decode the field, but AFAIK it is not indexable in mysql.
Using an external search engine is out of scope.
Ok, i didnt want to change the db strucure, i gost some help and changed the regex intoAND extra_fields REGEXP BINARY '(.*{"id":"2","value":\[("[^\"]*[123][^\"]*",?)+\]}.*)'
and i got the right resaults
Thanks