CDS LIKE filter from view parameter - abap

How to create a CDS that select all KUNNR from table KNA1 that Customer Number starts for example with A%.
I could use LIKE in the where clause but the RHS of the condition have to be static. It should depend on the input parameter from CDS.
Is it possible to do it with CDS?

I see two options.
You get rid of your CDS input parameter handling and move the logic to ABAP. Write your OPEN SQL select on your CDS with like statement.
Use CDS Table function and AMDP by pushing the like statement down to HANA native. Just follow my post here.
Hope it helps.

Related

AMDP selects false records contrary to OpenSQL

I am learning AMDP and I found out that the result obtained from this is very different from normal select query in ABAP AS.
I am using below code in AMDP:
ex_gt_data = select a.vbeln,
a.kunnr,
a.bukrs_vf,
b.erdat,
b.lsmeng,
b.posnr,
b.matnr
from vbak as a
join vbap as b
on a.vbeln = b.vbeln;
followed by APPLY_FILTER function.
This query return multiple values in BUKRS_VF field. If I use normal select query like below:
SELECT a~vbeln,
a~bukrs_vf,
a~kunnr,
b~erdat,
b~lsmeng,
b~posnr,
b~matnr
FROM vbak AS a
JOIN vbap AS b
ON a~vbeln = b~vbeln
INTO TABLE #DATA(lt_vbak)
WHERE a~vbeln IN #s_vbeln.
it generates required result.
Can anybody tell me why this difference between AMDP and normal select query?
I just found out that adding
MANDT
field
solves the issue. i have added an pass by value parameter in method and used in query as
where a.mandt = im_mandt.
Dont know whether this is the correct solution.Please advise.
Many discrete useful pieces were given, but I am here to give a comprehensive answer to the question.
First of all, ABAP CDS views do not respect client data automatically like it is done in OpenSQL. BTW, the same is true for HANA CDS but judging on indirect indicators of your question it was about ABAP CDS based on HANA backend, rather that HANA CDS. Ya?
What is the proper way of client handling in ABAP CDS views?
#ClientHandling.type #CLIENT_DEPENDENT annotation must be added to view.
Default type is #INHERITED but for more straightforwardness it's better make it explicitly dependent.
#ClientHandling.algorithm is an optional field and can be omitted. There is a complex set of rules which determines how the client is calculated but in your case you can just don't specify it, implicit #AUTOMATED way will be used and client column will be implicitly added to ON conditions of your JOIN.
Client column must exist in view and should be either
selected via SELECT statement with either name or alias
have MANDT name manually set
if the latter is absent CLIENT column is used
if neither CLIENT nor MANDT column is not found the syntax error is thrown
No other actions needed, client is addressed implicitly like in OpenSQL case.
But! Here we are speaking about AMDP procedure, not simple CDS, so the things are more tricky.
The first and foremost, for all this to work a special CDS SESSION CLIENT CURRENT AMDP declaration is mandatory in a method signature:
AMDP OPTIONS READ-ONLY
CDS SESSION CLIENT CURRENT
the declaration makes implicit passing of $session.client var into the implementation of AMDP procedure. In the default CURRENT syntax variant it is equal to sy-mandt value of ABAP AS.
After that you can use $session.client explicitly with tables inside AMDP
SELECT * FROM vbak WHERE vbak.mandt = $session.client;
or implicitly with client-dependent views
lt_vbak = APPLY_FILTER ("Z_CDS_VIEW", :iv_where);
You don't HAVE to add the MANDT parameter to get the client number in AMDP/generated SQL script. Rather, you can use SESSION_CONTEXT('CLIENT')
So, your above query would look like the following:
ex_gt_data = select a.vbeln,
a.kunnr,
a.bukrs_vf,
b.erdat,
b.lsmeng,
b.posnr,
b.matnr
from vbak as a
join vbap as b
on a.vbeln = b.vbeln
and a.mandt = SESSION_CONTEXT('CLIENT');
There are many more things you can achieve using SESSION_CONTEXT. Used properly, it's a powerful tool at your disposal.
Best Regards,
Gopal Nair.

how to use SQL user defined function in snowflake?

I am just studying how to use SQL in snowflake. Here is a snapshot:
And this is the code used in here:
use schema SNOWFLAKE_SAMPLE_DATA.TPCH_SF1;
--use schema SNOWFLAKE_SAMPLE_DATA.TPCH_SF10;
select *
from LINEITEM
limit 200
You can see the table includes two feilds: L_LINENUMBER, L_QUANTITY. Now I want to try a user defined function, which can do:
use L_LINENUMBER, L_QUANTITY as two parameters transferred into the function,
calculate L_LINENUMBER1=L_LINENUMBER+1, and L_QUANTITY1=mean(L_QUANTITY).
join the two new fields (L_LINENUMBER1, L_QUANTITY1) to the original table (LINEITEM)
how to use create function to do this. I have read a lot of examples regarding create function. But I just cannot get the point. Maybe because I am not good at SQL. So, could anyone give me a comprehensive example with all the details?
I understand that you question is about UDFs, but using UDFs for your purpose here is overkill.
You can increment an attribute in a table using the following statement.
SELECT
L_LINENUMBER+1 as L_LINENUMBER1
FROM LINEITEM;
To calculate the mean of an attribute in a table, you should understand that this is an aggregate function which only makes sense when used in conjunction with a group by statement. An example with your data is shown below.
SELECT
AVG(L_QUANTITY) AS L_QUANTITY1
FROM LINEITEM
GROUP BY L_ORDERKEY;
Since your question was originally on UDFs and you seem to be following with Snowflake's sample data, the example that they provide is the following UDF which accepts a temperature in Kelvin and converts it to Fahrenheit (from the definition you can see that it can be applied to any attribute of the number type).
CREATE OR REPLACE FUNCTION
UTIL_DB.PUBLIC.convert_fahrenheit( t NUMBER)
RETURNS NUMBER
COMMENT='Convert from Kelvin from Fahrenheit'
AS '(t - 273.15) * 1.8000 + 32.00';

View with parameters in BigQuery

We have a set of events (kind of log) that we want to connect to get the current state. To improve performance/cost further, we would like to create snapshots (in order to not check all the events in history, but only from the last snapshot). Logs and snapshots are the tables with date suffix.
This approach works OK in the BQ, but we need to manually define the query every time. Is there any way to define 'view' with parameters (e.g. dates for the table range query)? Or any plans to do something like that?
I know that there are some topics connected with TABLE_RANGE / QUERY in views (eg Use of TABLE_DATE_RANGE function in Views). Are there any new information on this subject?
That's a great feature request - but currently not supported. Please leave more details at https://code.google.com/p/google-bigquery/issues/list, the BigQuery team takes these requests very seriously!
As a workaround i wrote a small framework to generate complex queries with help of velocity templates. Just published it at https://github.com/softkot/gbq
Now you can use Table Functions (aka table-valued functions - TVF) to achieve this. They are very similar to a view but they accept a parameter. I've tested and they really help to save a lot while keeping future queries simple, since the complexity is inside the Table Function definition. It receives a parameter that you can then use inside the query for filtering.
This example is from the documentation:
CREATE OR REPLACE TABLE FUNCTION mydataset.names_by_year(y INT64)
AS
SELECT year, name, SUM(number) AS total
FROM `bigquery-public-data.usa_names.usa_1910_current`
WHERE year = y
GROUP BY year, name
Then you just query it like this:
SELECT * FROM mydataset.names_by_year(1950)
More details can be found in the oficial documentation.
You can have a look at BigQuery scripting that have been released in beta : https://cloud.google.com/bigquery/docs/reference/standard-sql/scripting

SAP passing data from application to screen. How does 'TABLES' work?

I don't quite understand how the TABLES statement works in ABAP. From a few example codes I've seen that the tablename afther the statement is an already existing dictionary structure. Is this the only way it can be used? Because I'm never sure which structure it is that I need.
And once it is declared how do I pass this to the actual screen? I wish it were as straight forward as the HIDE method, I can't get my head around this.
The tables statement just provides you with a single-line work area of the dictionary structure that you specify. It allows you to use fields of the structure as select-options and make the structure of the table available as a variable in your program.
If you are trying to write the structure to an abap list you could use it as follows:
tables: aufk.
select single * from aufk into aufk
where aufnr = some_order_number.
"I'm pretty sure the into clause is optional
"because of the tables statement, but including it to be explicit.
write / aufk.
If you are trying to display the field using ABAP dynpro, you should make sure that you read the field in the PBO and add the field(s) to the screen from the dictionary.

How to pass an entire row (in SQL, not PL/SQL) to a stored function?

I am having the following (pretty simple) problem. I would like to write an (Oracle) SQL query, roughly like the following:
SELECT count(*), MyFunc(MyTable.*)
FROM MyTable
GROUP BY MyFunc(MyTable.*)
Within PL/SQL, one can use a RECORD type (and/or %ROWTYPE), but to my knowledge, these tools are not available within SQL. The function expects the complete row, however. What can I do to pass the entire row to the stored function?
Thanks!
Don't think you can.
Either create the function with all the arguments you need, or pass the id of the row and do a SELECT within the function.