OpenEdge BREAK-BY QTY and Sum of rows - openedge

I have an orderline table which has QTY field and I would like to group items the way it is shown in image.
I tried using this:
FOR EACH RobotOrderline NO-LOCK
BREAK BY RobotOrderline.OrderedQty.
DISPLAY RobotOrderline.OrderedQty.
END.
But even the grouping seems wrong.

You need to actually sum the quantities. Also the for each still runs for each row in the table, it only orders them and sets flag for different locations in the order (first, last, first-of, last-of).
DEFINE VARIABLE iQty AS INTEGER NO-UNDO.
FOR EACH RobotOrderline NO-LOCK
BREAK BY RobotOrderline.OrderedQty.
iQty = iQty + RobotOrderline.OrderedQty.
IF LAST-OF(RobotOrderline.OrderedQty) THEN DO:
DISPLAY RobotOrderline.OrderedQty iQty.
iQty = 0.
END.
END.

Related

Problem inserting database row using last row in sqlite

I'd like to be able to do the following initially and also at anytime.
insert into balance (closing_amount, opening_amount, created, tx_id)
select closing_amount + :value, closing_amount, :date, :tx_id from balance order by id desc limit 1
Basically I'm inserting by using previous values. But if there are no values to begin with, nothing gets inserted.
I could use a union to which works the first time but duplicates on subsequent inserts.
I want to avoid two trips. Is there a way to do this?
Also, the tx_id will always be unique.
I think you want something like this:
insert into balance (closing_amount, opening_amount, created, tx_id)
select coalesce(max(closing_amount), 0) + :value,
coalesce(max(closing_amount), 0),
:date,
:tx_id
from (
select closing_amount
from balance
order by tx_id desc
limit 1
) t;
You only need the last closing_amount, so max(closing_amount) from the subquery, which returns 1 row or none at all, will return that closing_amount or null respectively.
See a simplified demo.

Finding maximum and minimum value from a field

I have a temp table ttsales which contains a field name t_sales of integer type, I want to find out the maximum and minimum value from a t_sales And on a button click those maximum and minimum value will show. what can I do?
One possibility is to sort the temp-table in ascending and descending order. Adding an index will help. If you cant change the temp-table and its large this might not be the best solution.
DEFINE TEMP-TABLE ttsales NO-UNDO
FIELD t_sales AS INTEGER
INDEX sales t_sales.
DEFINE VARIABLE iMin AS INTEGER NO-UNDO.
DEFINE VARIABLE iMax AS INTEGER NO-UNDO.
CREATE ttsales.
ASSIGN ttsales.t_sales = 10.
CREATE ttsales.
ASSIGN ttsales.t_sales = 1.
CREATE ttsales.
ASSIGN ttsales.t_sales = 130.
CREATE ttsales.
ASSIGN ttsales.t_sales = 2.
/* Get minimum value */
FOR EACH ttsales BY ttsales.t_sales:
iMin = ttsales.t_sales.
LEAVE.
END.
/* Get maximum value */
FOR EACH ttsales BY ttsales.t_sales DESCENDING:
iMax = ttsales.t_sales.
LEAVE.
END.
DISPLAY iMin iMax.
DEFINE QUERY qry FOR tsales.
OPEN QUERY qry FOR EACH tsales BY t_sales.
GET FIRST qry.
MESSAGE tsales.t_sales.
GET LAST qry.
MESSAGE tsales.t_sales.
Depending on size of table, add an index on the field.

How to delete DDIC table records which have different id than row number in internal table?

I have an ALV with two rows. I want to delete these rows in internal table and dictionary table also. To get which rows in alv i chose, i use a method
go_selections = go_salv->get_selections( ).
go_rows = go_selections->get_selected_rows( )
Nextly, i am iterating through results LOOP AT go_rows INTO gv_row.
Inside above loop I have an another loop, which stores data from internal table into workarea. Then, i set the counter variable which holds the id of the dictionary table and delete respective row.
LOOP AT gr_data INTO lr_znewfdkey6.
counter2 = lr_znewfdkey6-id.
IF counter2 EQ gv_row.
DELETE FROM znew_fdkey01 WHERE id EQ lr_znewfdkey6-id.
MESSAGE 'Row deleted .' TYPE 'I'.
But unfortunately this works only when id of the dictionary table is equal to row number selected in alv. If I have lr_znewfdkey6-id in dictionary table, equal to for example 5, get_selected_rows( ) returns value started by one etc., and this will cause inequality.
How to fix this?
Get selected rows returns a table of line numbers.
lt_rows = lo_selections->get_selected_rows( ).
Those numbers correspond directly to the itab you loaded into the ALV. No matter if it has been sorted or filtered. It does not correspond to any fields in the database like an ID field or anything.
Assuming gr_datais the itab assigned to the ALV. Let's loop lt_rows and read gr_data at index
LOOP AT lt_rows ASSIGNING FIELD-SYMBOL(<row>).
READ TABLE gr_data INTO ls_data INDEX <row>.
IF sy-subrc = 0.
APPEND ls_data TO lt_selected.
ENDIF.
ENDLOOP.
After executing this will collect selected gr_data lines into lt_selected itab. To delete
LOOP AT lt_selected ASSIGNING FIELD-SYMBOL(<row>).
DELETE TABLE gr_data FROM <row>.
ENDLOOP.
You could also simply do:
LOOP AT lt_rows ASSIGNING FIELD-SYMBOL(<row>).
DELETE gr_data INDEX <row>.
ENDLOOP.
After that refresh your ALV. Should be good.

how to get a unqiue result sets in PL/SQL cursor?

I want use this procedure to display the username and moblephone number,the result sets is this when I use select :
declare enter image description here
when the procedure runs,I get this :
enter image description here
error ORA-01722: invalid number
ORA-06512: at "ABPROD.SHAREPOOL", line 24.
when I use unique or distinct in the cursor,nothing display.
the code source :
create or replace procedure sharepool (assignment in varchar2,myorgname in varchar2) is
rightid T_CLM_AP30_RIGHT.RIGHT_ID%type;
orgid t_clm_ap30_org.org_id%type;
begin
select t.right_id into rightid from T_CLM_AP30_RIGHT t where t.rightdesc=trim(assignment);
dbms_output.put_line(rightid||trim(myorgname)||assignment);
select t.org_id into orgid from t_clm_ap30_org t where t.orgname=trim(myorgname);
dbms_output.put_line(orgid);
declare
cursor namelist is select distinct a.username,a.mobile from t_clm_ap30_user a, T_CLM_AP30_RIGHT_AUTH t where a.user_id=t.user_id and t.right_id=rightid and t.poolorgrange=orgid ;
begin
for c in namelist
loop
dbms_output.put_line(c.username||' '||c.mobile);
end loop;
end;
end sharepool;
INVALID_NUMBER errors indicate a failed casting of a string to a number. That means one of your join conditions is comparing a string column with a number column, and you have values in the string column which cannot be cast to a number.
ORA-06512: at "ABPROD.SHAREPOOL", line 24
Line 24 doesn't align with the code you've posted, presumably lost in translation from your actual source. Also you haven't posted table descriptions so we cannot tell which columns to look at.
So here is a guess.
One (or more) of these joins has an implicit numeric conversion:
where a.user_id = t.user_id
and t.right_id = rightid
and t.poolorgrange = orgid
That is, either t_clm_ap30_user.user_id is numeric and T_CLM_AP30_RIGHT_AUTH.user_id is not, or vice versa. Or T_CLM_AP30_RIGHT_AUTH.right_id is numeric and T_CLM_AP30_RIGHT.right_id is not, or vice versa. Or T_CLM_AP30_RIGHT_AUTH.poolorgrange is numeric and t_clm_ap30_org.org_id is not, or vice versa.
Only you can figure this out, because only you can see your schema. Once you have identified the join where you have a string column being compared to a numeric column you need to query that column to find the data which cannot be converted to a number.
Let's say that T_CLM_AP30_RIGHT_AUTH.poolorgrange is the rogue string. You can see which are the troublesome rows with this query:
select * from T_CLM_AP30_RIGHT_AUTH
where translate (poolorgrange, 'x1234567890', 'x') is not null;
The translate() function strips out digits. So anything which is left can't be converted to a number.
"T_CLM_AP30_RIGHT_AUTH.poolorgrange is varchar2,and t_clm_ap30_org.org_id is numeric ."
You can avoid the error by explicitly casting the t_clm_ap30_org.org_id to a string:
select distinct a.username, a.mobile
from t_clm_ap30_user a,
T_CLM_AP30_RIGHT_AUTH t
where a.user_id = t.user_id
and t.right_id = rightid
and t.poolorgrange = to_char(orgid) ;
Obviously you're not going to get matches on those alphanumeric values but the query will run.

MySQL Changing Order Depending On Contents of a Column

I have a MySQL table Page with 2 columns: PageID and OrderByMethod.
I also then have a Data table with lots of columns including PageID (the Page the data is on), DataName, and DataDate.
I want OrderByMethod to have one of three entries: Most Recent Data First, Most Recent Data Last, and Alphabetically.
Is there a way for me to tack an "ORDER BY" clause to the end of this query that will vary its ordering method based on the contents of the "OrderByMethod" column? For example, in this query, I would want to have the ORDER BY clause contain whatever ordering rule is stored in Page 1's OrderByMethod column.
GET * FROM `Data` WHERE `Data`.`PageID`=1 ORDER BY xxxxxx;
Maybe a SELECT clause in the ORDER BY clause? I'm not sure how that would work though.
Thanks!
select Data.*
from Data
inner join Page on (Data.PageID=Page.PageID)
where Data.PageID=1
order by
if(Page.OrderByMethod='Most Recent Data First', now()-DataDate,
if(Page.OrderByMethod='Most Recent Data Last', DataDate-now(), DataName)
);
You can probably do this with the IF syntax to generate a column that you can then order by.
SELECT *, IF(Page.OrderBy = 'Alphabetically', Data.DataName, IF(Page.OrderBy = 'Most Recent Data First', NOW() - Data.DataDate, Data.DataDate - NOW())) AS OrderColumn
FROM Data
INNER JOIN Page ON Data.PageID = Page.PageID
WHERE Page.PageID = 1
ORDER BY OrderColumn
The direction of the ordering is determined in the calculation of the data instead of specifying a direction in the ORDER BY
Can you just append the order by clause to the select statement and rebind the table on postback?
If you want to use the content of the column in Page table as an expression in ORDER BY you have to do it using prepared statements. Let say, you store in OrderByMethod something like "field1 DESC, field2 ASC" and you want this string to be used as it is:
SET #order_by =(SELECT OrderByMethod FROM Page WHERE id = [value]);
SET #qr = CONCAT(your original query,' ORDER BY ', #order_by);
PREPARE stmt FROM #qr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
If you want the result set to be sorted based on the value of OrderByMethod , you can use IF as it was already mentioned by others, or CASE :
...
ORDER BY
CASE OrderByMethod
WHEN 'val1' THEN field_name1
WHEN 'val2' THEN field_name2
....etc
END

Resources