Pentaho set field Value based on other field like in SQL - field

How can I set a field value of a Row in Pentaho for a new or an existing field depending on values in other fields of the same row like in a SQL select statement.
Doing this with a filter would be to time intensive doing this with multiple fields.
For example:
[Price] = CASE WHEN [Price Sold] <> 1 THEN [Price Sold] ELSE [Price Bought] END
[FX Currency] = CASE WHEN [Ccy Sold] <> [RefCcy] THEN [Ccy Sold] ELSE [Ccy Bought] END

I have solved my problem by using a Step:
"User Defined Java Expression"
New Field Java Expression
Price Price_Sold!=1?Price_Sold:Price_Bought

Related

An example of a Cursor & UPDATE statement in conjunction inside a procedure on Redshift

Would you please provide an an example for a Redshift procedure where you have used a cursor and an UPDATE statement in conjunction? Is that even feasible, I couldn't find an example. I'm looking for a simple template code to learn how to have these 2 together in a single procedure on Redshift.
Here is an example use case:
I have a table like this:
CREATE TABLE test_tbl
(
Contactid VARCHAR(500),
sfdc_OppId_01 VARCHAR(500),
sfdc_OppId_02 VARCHAR(500),
sfdc_OppId_03 VARCHAR(500),
sfdc_OppId_04 VARCHAR(500),
sfdc_OppId_05 VARCHAR(500),
sfdc_OppId_06 VARCHAR(500)
)
I want to update each sfdc_OppId_xx with the relative value from another table; sfdc_tbl. Here is what sfdc_tbl looks like:
sfdc_contactId
sfdc_Opp_Id
AA123hgt
999999
AA123hgt
888888
AA123hgt
777777
AA123hgt
432567
AA123hgt
098765
AA123hgt
112789
So as you see, there are duplicate sfdc_contactid in the sfdc_tbl. My final goal is to list all the sfdc_Opp_Id for given contactid horizontally in the test_tbl. I shall not have duplicate contactid in the test_tbl.
INSERT INTO test_tbl (Contactid)
SELECT sfdc_contactId
FROM sfdc_tbl
GROUP BY sfdc_contactId
And here is what I'm trying to do:
CREATE OR REPLACE PROCEDURE testing_procedure (results INOUT refcursor)
AS
$$
BEGIN
OPEN cursor_testing FOR
SELECT
Ops.sfdc_Opp.id,
ROW_NUMBER () OVER(PARTITION BY Ops.sfdc_contactId ORDER BY sfdc_Opp_Id ) RWN
FROM sfdc_tbl Ops
INNER JOIN test_tbl tbl
ON Ops.sfdc_contactId = tbl.contactid;
UPDATE test_tbl
SET sfdc_Opp_01 = CASE WHEN cursor_testing.RWN = 1 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_02 = CASE WHEN cursor_testing.RWN = 2 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_03 = CASE WHEN cursor_testing.RWN = 3 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_04 = CASE WHEN cursor_testing.RWN = 4 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_05 = CASE WHEN cursor_testing.RWN = 5 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_06 = CASE WHEN cursor_testing.RWN = 6 THEN cursor_testing.sfdc_Ops_id ELSE NULL END
;
END;
$$
LANGUAGE plpgsql;
I keep getting an error
incorrect syntax at or near "cursor_testing"
I've answered a question with a similar solution. The SQL uses a cursor's data to INSERT into a table and this same path should work for UPDATE - How to join System tables or Information Schema tables with User defined tables in Redshift
That being said and looking at your code I really think you would be better off using a temp table rather than a cursor. The first thing to note is that a cursor is not a table. Your use pattern won't work AFAIK. You read a cursor row by row (or bunches) which is contrary to Redshift's columnar table storage. So you will need to loop on the rows from the cursor and perform N updates. This will be extremely slow! You would be querying columnar data, storing the results in a cursor as rows, reading these row one by one, and then performing a new query (UPDATE) for each row. Ick! Stay in "columnar land" and use a temp table.

How to properly parameterize my postgresql query

I'm trying to parameterize my postgresql query in order to prevent SQL injection in my ruby on rails application. The SQL query will sum a different value in my table depending on the input.
Here is a simplified version of my function:
def self.calculate_value(value)
calculated_value = ""
if value == "quantity"
calculated_value = "COALESCE(sum(amount), 0)"
elsif value == "retail"
calculated_value = "COALESCE(sum(amount * price), 0)"
elsif value == "wholesale"
calculated_value = "COALESCE(sum(amount * cost), 0)"
end
query = <<-SQL
select CAST(? AS DOUBLE PRECISION) as ? from table1
SQL
return Table1.find_by_sql([query, calculated_value, value])
end
If I call calculate_value("retail"), it will execute the query like this:
select location, CAST('COALESCE(sum(amount * price), 0)' AS DOUBLE PRECISION) as 'retail' from table1 group by location
This results in an error. I want it to execute without the quotes like this:
select location, CAST(COALESCE(sum(amount * price), 0) AS DOUBLE PRECISION) as retail from table1 group by location
I understand that the addition of quotations is what prevents the sql injection but how would I prevent it in this case? What is the best way to handle this scenario?
EDIT: I added an extra column to be fetched from the table to highlight that I can't use pick to get one value.
find_by_sql is used when you want to populate objects with a single line of literal SQL. But we can use ActiveRecord for most of this, we just need one single column. To make objects, use select. If you just want results use pluck.
As you're picking from a fixed set of strings there's no risk of SQL injection in this code. Use Arel.sql to pass along a SQL literal you know is safe.
def self.calculate_value(result_name)
sum_sql = case result_name
when "quantity"
"sum(amount)"
when "retail"
"sum(amount * price)"
when "wholesale"
"sum(amount * cost)"
end
sum_sql = Arel.sql(
"coalesce(cast(#{sum_sql} as double precision), 0) as #{result_name}"
)
return Table1
.group(:location)
# replace pluck with select to get Table1 objects
.pluck(:location, sum_sql)
end

Rails - Search POstgres JSONB column based on key

I have a table abcs with denom_qty jsonb column. The value stored will be in the format
{"100"=>5, "1000"=>2}
I want to filter all the rows where the denom_qty colum has key >= a given value say 100.
I am aware that if the data is stored in the format
{ "denomination" => 100, "quantity"=> 2}. then I found multiple answers. But as the data structure cannot be changed now, how can I query all rows which has denom_qty colum's key greater than 100 ?
I think you can create a function based on json key values and check there is key is greater than 100.
Eg.
create function jsonkey( inpt jsonb)
returns jsonb
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
DECLARE
keyobj text[];
BEGIN
select array_agg(a.data) from(select jsonb_object_keys('{"100":5, "1000":2, "5":41}'::jsonb) as data )a into keyobj;
For i in select (keyobj)
LOOP
if(i >=100) THEN
return '{"100":5, "1000":2, "5":41}'::jsonb->>i;
ELSE
return '{}'::josnb;
END IF;
END LOOP;
END;
$BODY$;
Hope this help.

Stored Procedures reading a value of Min()

I am trying to find the minimum value of a primary key column of type (int) in a particular Table
A portion of my Stored Procedure Code:
IF NOT EXISTS
(
SELECT *
FROM Table
)
BEGIN
SELECT *
FROM Table
END
ELSE
BEGIN
SELECT Min(ColumnOne)
FROM Table
END
This is my main code after reading:
if (!reader.Read())
return "EMPTY TABLE";
else
return reader.GetInt32(0).ToString();
My ExecuteReader has no problem but when I got an exception at the statement
reader.GetInt32(0).ToString()
I believe I extract the information wrongly when my tables have more than one entry. What is the correct function I should call from reader to get the number??
i didn't get your Question.
AS you specify min() Value in Question And you wrote max() Function in T-SQL Script.
You Can try below if you want to retrieve next Val of a Column
Select isnull(max(ColumnOne),0)+1 FROM Table
Above Query will return you
1 in case Table is empty
else max current Value+1(Next Available Value)
from Table.

Cassandra cql comparator type counter

i want to use the following code for updating a field...
##db.execute("UPDATE user_count SET counters = counters + #{val} WHERE cid = 1 ")
First time i tried that i got the following fail:
CassandraCQL::Error::InvalidRequestException: invalid operation for non commutative columnfamily user_count
I found out that i have to use the comparator counter, but i cant find how i can setup that with the cassandra-cql gem... does anybody know how i can get this to work?
below there is my code that does not work ...
##db.execute("CREATE COLUMNFAMILY user_count(cid varchar PRIMARY KEY, counters counter) with comparator = counter " )
##db.execute("INSERT INTO user_count (cid, counters) VALUES (?,?)", 1, 0)
You need to set default_validation=CounterColumnType instead of comparator.
##db.execute("CREATE COLUMNFAMILY user_count(cid varchar PRIMARY KEY, counters counter) with default_validation=CounterColumnType")
##db.execute("update user_count set counters = counters + 1 where cid = 1")
You must use 'update' to change the counter value, there is no insert syntax for counters (in CQL update and insert do the same thing so you can create new rows using update).
Currently you cannot have counters and non-counters in the same column family (from the wiki: "A column family either contains only counters, or no counters at all.")

Resources