Totalling up values across salesforce account hierarchies - salesforce

I'm struggling to find an approach to the following problem, can anyone suggest a high level approach.
Using talend, I have an input set of values for a set of accounts (from CSV):
AccountId, ValueXYZ__c
I want to store ValueXYZ against the SFDC account, which is no problem, but then I want to totalise ValueXYZ up for all the accounts with the same parent to
Account.Parent.TotalValueXYZ
I then want to "roll" this all the way up the accounts hierarchy:
Imagine account hierarchy:
A
-B
--C
--D
-E
--F
--G
I want 3 values on A:
ValueXYZ = account A's ValueXYZ
TotalValueXYZ = total of ValueXYZ values for all accounts under A in the hierarchy
TOTAL = formula field to add together the previous 2 values
I want 3 values on account B
ValueXYZ = account B's ValueXYZ
TotalValueXYZ = total of ValueXYZ values for accounts C & D
TOTAL = formula field to add together the previous 2 values
I want 3 values on account C
ValueXYZ = account C's ValueXYZ
TotalValueXYZ = 0
TOTAL = formula field to add together the previous 2 values
I've tried several approaches, but can't get any of them to work!

Where is the hierarchy information stored? If you can flatten the hierarchy information in a key-value pair format, then it is straightforward. Just read your input file and do a lookup/join on the hierarchy file. You will have to loop through until you get to the base record

The crux of my problem was in not knowing each accounts position in a hierarchy. Once I had that in place, I could loop from the lowest level to the highest level, totalling these values up to their parents.
Here is the T-SQL I wrote to mark each account with it's Hierarchy Position (HILEVEL)
TRUNCATE TABLE [TALEND_WORKSPACE].[dbo].[SFDCAccount]
INSERT INTO [TALEND_WORKSPACE].[dbo].[SFDCAccount] (Id, ParentId, QCIYTDOneTime, QCIYTDRecurring, HILEVEL)
SELECT Id, ParentId, ValueXYZ, '0'
FROM [TALEND_WORKSPACE].[dbo].[SFDCAccountRawData]
WHERE ParentId = ' ';
USE TALEND_WORKSPACE
IF OBJECT_ID('dbo.sfdcaccounthierarchy', 'P') IS NOT NULL
DROP PROCEDURE [dbo].[sfdcaccounthierarchy];
GO
CREATE PROCEDURE [dbo].[sfdcaccounthierarchy]
AS
DECLARE #v_counter int;
DECLARE #v_lastccounter int;
DECLARE #v_max int;
SET #v_counter = 0;
SET #v_lastccounter = 0;
SET #v_max = 10;
WHILE (#v_counter < #v_max)
BEGIN
SET #v_lastccounter = #v_counter;
SET #v_counter = #v_counter+1;
PRINT #v_counter;
INSERT INTO [dbo].[SFDCAccount] (Id, ParentId, QCIYTDOneTime, QCIYTDRecurring, HILEVEL)
SELECT Id, ParentId, ValueXYZ, #v_counter
FROM [TALEND_WORKSPACE].[dbo].[SFDCAccountRawData]
WHERE ParentId IN (SELECT Id FROM [TALEND_WORKSPACE].[dbo].[SFDCAccount]
WHERE HILEVEL = #v_lastccounter);
if ##ROWCOUNT != 0
BREAK;
END
GO
EXEC [TALEND_WORKSPACE].[dbo].[sfdcaccounthierarchy];

Related

Mapping ID values using SQL

Assume you have 2 DB with matching table structures in both.
For example,
D1.T1(ID, VAL) = D2.T1(ID,VAL)
D1.T2(ID, NAME,FID) = D2.T2(ID, NAME,FID)
Where D1.T2.FID = D1.T1.ID
Now I want to copy rows from D1 to D2. But ID values changes during the insert into D2 (not because I can't force insert the same ID by using IDENTITY_INSERT, its because the same ID exist in D2.T1 for some other values).
Now I need to update the D2.T2 with the new identity values. How can this be done, without altering tables (to persist the old_id value in D2.T1 and doing an update later on on D2.T2 by comparing the old id value)?
To give a hint of the tables structure see below.
D1.T1
ID, VAL
4934, A
4936, B
5011, C
D1.T2
ID, NAME, FKID
2478, I, 4934
2479, II, 4936
2481, III, 5011
D2.T1
ID, VAL
7813, A
7817, B
7819, C
D2.T2
ID, NAME, FKID
3416, I, 7813
3417, II, 7817
3419, III, 7819
So, for example, we now come across a
D1.T1 of 7813, D
and then discover that 7813 already exists in D2.T1??
"But ID values change during the insert into D2"
What does it change to? say 9876 ?? So now D2.T1 would be 9876, D
Well, lets go on and try to copy
D1.T2 of 2482, IIII, 7813
BUT WAIT >> How do we know if this 7813 refers to 7813, A or 7813, D
We don't know, We cannot determine if we need to keep 7813 or change to 9876.
Ergo, we need more information that resides in the table, e.g. another column.

SQL Server - selecting a specific ID from a table

I will explain what I have done so far and ask my question at the end.
First I created my external & internal variables (note that #EDelivery is a table type that included the columns FoodID and Quantity):
#EDelivery DeliveryTblType readonly
Declare #NumberOfMinutes smallint, #FoodWeight int, #WeightCapacity int,
#DroneID int, #TimeOfWeek varchar
I then read this in, giving me the total weight of all items ordered and read in the weight capacity from the DronesTbl:
select #FoodWeight = SUM(FoodWeight * Quantity)
from #EDelivery as del
inner join Foods on del.FoodID = Foods.FoodID
select #WeightCapacity = Drones.WeightCapacity
from dbo.Drones
My question is how do I select a specific drone to compare its weightcapacity to the food total weight
You need to set the variable #WeightCapacity according to the #droneid value. Right now, you are setting this variable to last drone in your drones table.
If you change your second query to what's below then it should work.
select #WeightCapacity =
Drones.WeightCapacity
from dbo.Drones
where DroneID =#droneID

Need to eliminate the last 4 characters in a string(varchar)

i am using a stored procedure, where it is taking policy number as parameter which is varchar. I need to eliminate the last 4 characters of the policy number when we retrive from the tables. But the data for policy numbers is not consistent, so I am confused how to use the logic for this. The sample policy numbers are:
KSDRE0021-000
APDRE-10-21-000
KSDRE0021
APDRE-10-21
These are four formats where policies are there in our tables.For some policies there is no tailing end '-000', so that is the challenging part. Now, I need to eliminate the tailing part '-000' from the policies when I retrieve the data from tables.
This is the sample code, which is pulling the policy data from tables.
Create Proc usp.dbo.policydataSP #policy_num varchar(18)
AS
Begin
Select * from policy_table pt
where pt.policy_num = #policy_num
End
STEP 1: Create a User Defined Function to normalize a policy number.
create function dbo.normalize_policy_num
(#policy_num varchar(100))
returns varchar(100)
as
begin
-- replace trailing digits
if (#policy_num like '%-[0-9][0-9][0-9]')
set #policy_num = left(#policy_num, len(#policy_num) - 4)
-- replace remaining hyphens
set #policy_num = replace(#policy_num, '-', '')
return #policy_num
end
What this essentially doing is stripping off the trailing '-000' from policy numbers that contain the pattern, then removing remaining hyphens. This function seems to work on your supplied policy numbers:
-- returns: KSDRE0021
select dbo.normalize_policy_num('KSDRE0021-000')
-- returns: APDRE1021
select dbo.normalize_policy_num('APDRE-10-21-000')
-- returns: KSDRE0021
select dbo.normalize_policy_num('KSDRE0021')
-- returns: APDRE1021
select dbo.normalize_policy_num('APDRE-10-21')
STEP 2: Modify your SP as follows:
create proc usp.dbo.policydataSP
#policy_num varchar(18)
as
begin
select
dbo.normalize_policy_num(pt.policy_num) as normalized_policy_num,
pt.*
from policy_table pt
where dbo.normalize_policy_num(#policy_num) = dbo.normalize_policy_num(pt.policy_num)
Note: If you are able to modify the table schema, you could add a persisted computed column using the UDF specified above. If you add an index to it, queries will run much faster. However, there will be some penalty for inserts, so there is a trade-off.
this is probably your best bet. Match the policy number up to the length of the requested parameter:
Create Proc usp.dbo.policydataSP
#policy_num varchar(18)
AS
Begin
Select * from policy_table pt where LEFT(len(#policy_num),pt.policy_num) = #policy_num
End
If you only want to strip -000 when returning results:
select case right(policy_num, 4)
when '-000' then left(policy_num, len(policy_num) - 4)
else policy_num end as policy_num
from policy_table pt
where pt.policy_num = #policy_num
If you want to strip any 3-digit value following a dash:
select case when policy_num like '%-[0-9][0-9][0-9]' then left(policy_num, len(policy_num) - 4)
else policy_num end as policy_num
from policy_table pt
where pt.policy_num = #policy_num

Update a table with scope identity from new inserted row

I have a table in which I need to update one column with ticketnumbers.
These ticketnumbers are created in another table where it is an identity field.
This code doesn't work. Why?
UPDATE sheet10
SET [TicketNummer] = (INSERT INTO ticketnummers (AangemaaktOp, aangemaaktdoor,verwijderd,afgewezen) VALUES ('2014-01-20 15:00:00',100,0,0) SELECT SCOPE_IDENTITY() )
where isnumeric([TicketNummer]) = 0
What am I doing wrong?
rg.
Eric
Composable DML should let you INSERT only if the UPDATE has a row matching
However...
how do you correlate rows?
What happens for concurrent inserts?
What if multiple rows have no TicketNummer value in sheet10
and many other questions
In summary, this is possible even if I'd never actually do it given the design questions
UPDATE
sheet10
SET
TicketNummer = (
SELECT
*
FROM
(
INSERT INTO ticketnummers (AangemaaktOp, aangemaaktdoor,verwijderd,afgewezen)
OUTPUT INSERTED.IDColumn
VALUES ('2014-01-20 15:00:00', 100, 0, 0)
) X
)
WHERE
ISNULL(TicketNummer, 0) = 0;
You cannot use INSERT in this way. It has to be statement on its own.
Basically you have to perform this operation in 2 steps:
INSERT INTO ticketnummers (AangemaaktOp, aangemaaktdoor,verwijderd,afgewezen) VALUES ('2014-01-20 15:00:00',100,0,0);
UPDATE sheet10
SET [TicketNummer] = SCOPE_IDENTITY()
where ISNULL([TicketNummer], 0) = 0

Oracle Triggers Update at Another Table

I am trying to create a trigger in Oracle. I know sql but i have never created trigger before. I have this code:
create or replace trigger "PASSENGER_BOOKING_T1"
AFTER
insert on "PASSENGER_BOOKING"
for each row
begin
IF (:NEW.CLASS_TYPE == 'ECO')
SELECT F.AVL_SEATS_ECOCLASS,F.FLIGHT_ID INTO SEAT, FLIGHT_INFO
FROM BOOKING B, JOURNEY_FLIGHT J, FLIGHT F
WHERE B.JOURNEY_ID = J.JOURNEY_ID and F.FLIGHT_ID = J.FLIGHT_ID;
UPDATE FLIGHT
SET AVL_SEATS_ECOCLASS = (SEAT-1)
WHERE FLIGHT_ID = FLIGHT_INFO;
END IF;
end;​
This trigger fires when there is an insert in Passenger_Booking table. And seating capacity is reduced by one (which is at different table).
Select query should be alright but there is something wrong in somewhere.
Could anyone suggest anything?
I changed the body part to this but still having issues:
UPDATE FLIGHT
SET AVL_SEATS_ECOCLASS =
(SELECT F.AVL_SEATS_ECOCLASS FROM BOOKING B, JOURNEY_FLIGHT J, FLIGHT F WHERE B.JOURNEY_ID = J.JOURNEY_ID and F.FLIGHT_ID = J.FLIGHT_ID;
);
An IF statement needs a THEN
In PL/SQL, you use an = to test for equality, not ==
You need to declare the variables that you are selecting into
When I do those three things, I get something like this
create or replace trigger PASSENGER_BOOKING_T1
AFTER insert on PASSENGER_BOOKING
for each row
declare
l_seat flight.seat%type;
l_flight_id flight.flight_id%type;
begin
IF (:NEW.CLASS_TYPE = 'ECO')
THEN
SELECT F.AVL_SEATS_ECOCLASS,F.FLIGHT_ID
INTO l_seat, l_flight_id
FROM BOOKING B,
JOURNEY_FLIGHT J,
FLIGHT F
WHERE B.JOURNEY_ID = J.JOURNEY_ID
and F.FLIGHT_ID = J.FLIGHT_ID;
UPDATE FLIGHT
SET AVL_SEATS_ECOCLASS = (l_seat-1)
WHERE FLIGHT_ID = l_flight_id;
END IF;
end;​
Beyond those syntax errors, I would be shocked if the SELECT INTO statement was correct. A SELECT INTO must return exactly 1 row. Your query should almost certainly return multiple rows since there are no predicates that would restrict the query to a particular flight or a particular booking. Presumably, you want to join to one or more columns in the PASSENGER_BOOKING table.
Additionally, if this is something other than a homework assignment, make sure you understand that this sort of trigger does not work correctly in a multi-user environment.
just a wild guess
edit as Justin pointed out (thanks Justin) equality check
create or replace trigger "PASSENGER_BOOKING_T1"
AFTER
insert on "PASSENGER_BOOKING"
for each row
declare
v_flight_id FLIGHT.FLIGHT_ID%TYPE;
begin
IF (:NEW.CLASS_TYPE = 'ECO') THEN
SELECT F.ID into v_flight_id
FROM BOOKING B, JOURNEY_FLIGHT J, FLIGHT F
WHERE B.ID = :NEW.BOOKING_ID -- note that I've made this up
AND B.JOURNEY_ID = J.JOURNEY_ID AND F.FLIGHT_ID = J.FLIGHT_ID;
UPDATE FLIGHT
SET AVL_SEATS_ECOCLASS = (SEAT-1)
WHERE ID = v_flight_id;
END IF;
end;​

Resources