At change of kunnr delete lines or proceed - abap

I have an itab which has the fields kunnr, bukrs, prodgrp & amound.
I have the below lines:
150 1000 adsl 10
150 1000 adsl1 15
150 1000 adsl2 20
150 8000 vdsl 25
150 8000 vdsl1 10
200 1000 adsl1 80
200 1000 adsl2 80
I want to do the following:
At the end of each customer sum the amount and if it is less than the amount that put the user in selection screen, delete the lines of itab. If it is bigger leave them. This itab at the end of the program will be displayed.
Any idea on how to do it in a quick way?

Instead of deleting in the current itab, I would use a new itab and only add the aggregations that match your condition.
Take a look at this answer showing how to aggregate your data in a new itab, and use your user input threshold (pa_user_threshold) before the append.
IF pa_user_threshold >= lf_sum.
APPEND ls_agg TO lt_agged.
ENDIF.

Related

SAS - Advanced querying

I have one SQL table with the data in SAS. The first column is a datetime, and there is one row for each second. The set spans for about 20 minutes. The other columns contain integer values.
Here is what I need:
For example, Let's pick 50. How many times did the integer value go from below 50 to above 50 and stay above 50 for at least n seconds.
Is it possible to conduct such analysis with proc sql? If yes, how so, and if not, how else?
I am new to SAS, so any help is appreciated. Let me know if you need more info!
Thanks!
How many times did the integer value go from below/above 50
I think this could be solution to first part of the question. Resolution is maybe the best obtained by comparing current value with prior
data begin; /*Some test data...*/
input int_in_question;
datalines;
51
51
49
55
55
40
40
60
40
;
run;
data With_calc;
set begin;
if int_in_question < 50 and
lag(int_in_question)>=50
then Times_below_50+1;
run;

Select minimum value from column A where column B is not in an array

I'm trying to select accesses for patients where d11.xblood is a minimum value grouped by d11.xpid - and where d11.xcaccess_type is not 288, 289, or 292. (d11.xblood is a chronological index of accesses.)
d11.xpid: Patient ID (int)
d11.xblood: Unique chronological index of patients' accesses (int)
d11.xcaccess_type: Unique identifier for accesses (int)
I want to report one row for each d11.xpid where d11.xblood is the minimum (initial access) for its respective d11.xpid . Moreover, I want to exclude the row if the initial access for a d11.xpid has a d11.xcaccess_type value of 288, 289 or 292.
I have tried several variations of this in the Select Expert:
{d11.xblood} = Minimum({d11.xblood},{d11.xpid}) and
not ({d11.xcaccess_type} in [288, 289, 292])
This correctly selects rows with the initial access but eliminates rows where the current access is not in the array. I only want to eliminate rows where the initial access is not in the array. How can I accomplish this?
Sample table:
xpid xblood xcaccess_type
---- ------ -------------
1 98 400
1 49 300
1 152 288
2 33 288
2 155 300
2 70 400
3 40 300
3 45 400
Sample desired output:
xpid xblood xcaccess_type
---- ------ -------------
1 49 300
3 40 300
See that xpid = 2 is not in the output because its minimum value of xblood had an xcaccess_type = 288 which is excluded. Also see that even though xpid = 1 has an xcaccess_type = 288, because there is a lower value of xblood for xpid = 1 where xcaccess_type not in (288,289,292) it is still included.
If you don't want to write a stored procedure or custom SQL to handle this, you could add another Group. Assuming your deepest group (the one closest to the Details section) is sorting based on xpid, you could add a group inside that one which sorts the xcaccess_type from lowest to highest.
Suppress the header and footer for the new group then add this clause to the details section:
({d11.xpid} = PREVIOUS({d11.xpid})
OR
({d11.xcaccess_type} in [288, 289, 292])
This should modify your report to only ever display the records with the lowest access value per person. And if the lowest access value is one of the three forbidden values, no records will show for that xpid.

Excel VBA SubTotals

Excel build-in functions are, at most of the time, effective. However, there are some functions really like implemented half-way and some how dictated their usage. The SUBTOTAL function is one of them.
My data is presented in the following format:
Value Count
100 20
102 3
105 4
102 5
And I want to build a table in this format:
Value Count
100 20
101 0
102 8
103 0
104 0
105 4
I've read this in SO but my situation is a bit differ. Pivot table will be able to give you the subtotals of the values appears in the original data and I don't want to have a loop to insert missing values in the original data (if it is gonna to be a loop over the original data, the loop could use to build the table - which I would prefer to avoid at all)

SQL Query Recalculating Running Totals

I'm taking a set of transactions and amounts, and I want to create a new amount column, with the following logic --
Check a running total of (new) amounts thus far.
If adding this amount to the previous total would bring the total to less than zero, the new amount field should be zero. Otherwise, it should be equal to the old amount.
Here's an example of what I'm looking for --
Item Record Old amount New Amount Running Total
1 1 100 100 100
1 2 -100 -100 0
1 3 -200 0 0
1 4 500 500 500
1 5 -300 -300 200
1 6 300 300 500
My running total starts at zero.
My first amount is 100, and that doesn't take the total < 0, so I pass it through and set the
new amount to 100.
My second amount is -100, and that doesn't take my running total of 100 to < 0, so I set the new amount to -100.
My third amount is -200. That would take the running total of 0 to -200, < 0. Thus, I set the new amount to 0.
My fourth amount is 500. It gets passed through.
My fifth amount is -300. That would take the running total of 500 to 200, which is still >= 0. It gets passed through.
My sixth amount is 300. It gets passed through, leaving me with a final amount total of 500.
The difficult part is in cases like record five here. In order to know that it won't take the final running total below zero, you need to have already calculated the new total for record 3.
I think you can do this by setting up common table expressions in order to make a recursive query, but I've foundered on how exactly to create that. If possible, I'd like to avoid cursors.
this is a WINDOW FUNCTION solution with a wrapping CASE statement.
look up LAG

how to find Sum(field) in condition ie "select * from table where sum(field) < 150"

I have to retrieve only particular records whose sum value of size field is <=150.
I have table like below ...
userid size
1 70
2 100
3 50
4 25
5 120
6 90
The output should be ...
userid size
1 70
3 50
4 25
For example, if we add 70,50,25 we get 145 which is <=150.
How would I write a query to accomplish this?
Here's a query which will produce the above results:
SELECT * FROM `users` u
WHERE (select sum(size) from `users` where size <= u.size order by size) < 150
ORDER BY userid
However, the problem you describe of wanting the selection of users which would most closely fit into a given size, is a bin packing problem. This is an NP-Hard problem, and won't be easily solved with ANSI SQL. However, the above seems to return the right result, but in fact it simply starts with the smallest item, and continues to add items until the bin is full.
A general, more effective bin packing algorithm would is to start with the largest item and continue to add smaller ones as they fit. This algorithm would select users 5 and 4.
What you're looking for is a greedy algorithm. You can't really do this with one SQL statement.
It's similar to the subset sum problem. You are definitely going to be into exponential time ...
There are several ways to solve subset
sum in time exponential in N. The most
naïve algorithm would be to cycle
through all subsets of N numbers and,
for every one of them, check if the
subset sums to the right number. The
running time is of order O(2^N*N), since
there are 2N subsets and, to check
each subset, we need to sum at most N
elements.
Unless you can constrain the problem to smaller subsets.
According to your definition as it stands you could get any of these tables:
userid size userid size
1 70 2 100
userid size userid size
3 50 4 25
userid size userid size
5 120 6 90
userid size userid size
1 70 2 100
3 50 3 50
userid size userid size
1 70 2 100
4 25 4 25
userid size userid size
1 70 4 25
3 50 6 90
4 25
userid size userid size
4 25 3 50
5 120 6 90
SQL sucks at guessing. Do you mean to say you want the most users who's total size is under a certain limit? You'll need to create a temp table of all the combinations of users, then select the ones who's total size is less then the limit, then select the one with the most users, and possibly the lowest user ID or something. Either way, it won't be fast due to the first step.
But do you want to maximize the number of results or minimize or you simply don't care? first two cases is constraints optimization for which there should be solution using SQL, the latter (as mentioned above) requires greedy strategy.