Calculate amounts in interval - sql

I have the following code from Navision
PrintLine := FALSE;
LineTotalVendAmountDue := 0;
FOR i := 1 TO 5 DO BEGIN
DtldVendLedgEntry.SETCURRENTKEY("Vendor No.","Initial Entry Due Date");
DtldVendLedgEntry.SETRANGE("Vendor No.","No.");
DtldVendLedgEntry.SETRANGE("Initial Entry Due Date",PeriodStartDate[i],PeriodStartDate[i + 1] - 1);
DtldVendLedgEntry.CALCSUMS("Amount (LCY)");
VendBalanceDue[i] := DtldVendLedgEntry."Amount (LCY)";
VendBalanceDueLCY[i] := DtldVendLedgEntry."Amount (LCY)";
IF VendBalanceDue[i] <> 0 THEN
PrintLine := TRUE;
LineTotalVendAmountDue := LineTotalVendAmountDue + VendBalanceDueLCY[i];
TotalVendAmtDueLCY := TotalVendAmtDueLCY + VendBalanceDueLCY[i];
END;
I have to translate the code above into SQL server but I can't understand it. I am a newbie with Navision.

Hard if even possible to translate to SQL given no context, but essentially:
For 5 date intervals (the start date of each specified in PeriodStartDate array) add up:
SELECT SUM([Amount (LCY)])
FROM [Company$Detailed Vendor Ledg. Entry]
WHERE [Vendor No.] = $1 -- particular Vendor No.
AND [Initial Entry Due Date] BETWEEN $2 and $3 -- period start/end, inclusive
LineTotalVendAmountDue is set to the total of 5 intervals for the specific Vendor.
TotalVendAmtDueLCY is set to report grand total (presumably).

Related

Alternative solution for the given problem

I asked the following question a few days back:
Repeating the data after a particular time period
I got the following code in answer:
execute immediate
$$
declare
num_loops number := 10; --set the number of loops you want to iterative and create data for
min_day number := 1; --filter for starting range from 1 to 3
max_day number := 3; --filter for ending range from 1 to 3
day_increase := 3; -- each day we want to add three new days
day_incrementer := 3; -- we need to keep track of what value we are currently on
insert_stmt varchar;
begin
let counter := 1;
while (counter < num_loops) do
insert_stmt :=
'INSERT INTO CITY_DATA
SELECT DAY +' || :day_increase || ', ITEM_CLASS, CITY, CUTOFF, TRANSFER FROM CITY_DATA
WHERE DAY BETWEEN ' || :min_day || ' and ' || max_day;
execute immediate :insert_stmt;
day_incrementer := day_incrementer + day_increase;
min_day := min_day + day_increase;
max_day := max_day + day_increase;
counter := counter + 1;
end while;
return counter || ' number of batches inserted with ending value of: ' || :day_incrementer;
end;
$$;
how do I run this code? I am getting continuous errors as "invalid identifier: num_loops" or unexpected
I am having hard time using this code, can anybody explain this or have an alternate answer to the above problem attached in the link.

adding to variables inside of a oracle procedure

I created a procedure that takes the account number of a user and it returns every transaction they've made plus their running balance. everything works except the balance. The code compiles and runs but nothing shows up in the running balance column of the dbms.output
CREATE OR REPLACE PROCEDURE print_dett(
in_account_nbr NUMBER
)
IS
dCount NUMBER;
BEGIN
dbms_output.put_line(' Date : transaction amount : balance - For: ' || in_account_nbr);
FOR r IN(
SELECT t.tx_nbr, t.tx_date, t.tx_amount, t.tx_type_code, a.balance
FROM transaction t, account a
WHERE t.account_nbr = a.account_nbr
AND t.account_nbr = in_account_nbr
ORDER BY tx_date)
LOOP
IF r.tx_type_code = 'D' OR r.tx_type_code = 'R' THEN
dCount := dCount + r.tx_amount;
ELSE
dCount := dCount - r.tx_amount;
END IF;
dbms_output.put_line(r.tx_date || ' : ' || r.tx_amount || ' : ' || dCount );
END LOOP;
END;
What can I change in the code so the running balance will actually show up when printed?
Number variables get initialized with NULL. Your variable dCount is hence null first and adding values doesn't change this.
Initialize it with zero instead:
CREATE OR REPLACE PROCEDURE print_dett(
in_account_nbr NUMBER
)
IS
dCount NUMBER := 0;
...

How to search for a month that is input by the user

I am working on some homework and have been stuck on this for a week. I have tried using TO_CHAR, MONTH(search), and EXTRACT(MONTH from...) and they all end up with either identifier 'JAN'(the month I am searching for) is not declared, or expression is of the wrong type. This assignment is to display all the rows for pledges made in a specified month. The column PLEDGEDATE is of type Date in the format 'dd-mmm-yy'. Any ideas how to make this work?
Declare
Pledges UNIT_2_ASSIGNMENT%ROWTYPE;
SEARCH DATE;
Begin
SEARCH := &M0NTH;
FOR PLEDGES IN
(SELECT IDPLEDGE, IDDONOR, PLEDGEAMT,
CASE
WHEN PAYMONTHS = 0 THEN 'LUMP SUM'
ELSE'MONHTLY - '||PAYMONTHS
END AS MONTHLY_PAYMENT
FROM UNIT_2_ASSIGNMENT
WHERE TO_CHAR(PLEDGEDATE,'MMM') = 'SEARCH'
ORDER BY PAYMONTHS)
LOOP
DBMS_OUTPUT.PUT_LINE('Pledge ID: '||UNIT_2_ASSIGNMENT.IDPLEDGE||
' Donor ID: '||UNIT_2_ASSIGNMENT.IDDONOR||
' Pledge Amount: '||TO_CHAR(UNIT_2_ASSIGNMENT.PLEDGEAMT)||
' Lump Sum: '||MONTHLY_PAYMENT);
END LOOP;
END;
You can use (comments on changes are inline):
DECLARE
Pledges UNIT_2_ASSIGNMENT%ROWTYPE;
SEARCH VARCHAR2(3); -- Use VARCHAR2 not DATE data type.
BEGIN
SEARCH := 'JAN'; -- Replace with your substitution variable.
FOR PLEDGES IN (
SELECT IDPLEDGE,
IDDONOR,
PLEDGEAMT,
CASE
WHEN PAYMONTHS = 0
THEN 'LUMP SUM'
ELSE 'MONHTLY - '||PAYMONTHS
END AS MONTHLY_PAYMENT
FROM UNIT_2_ASSIGNMENT
WHERE TO_CHAR(PLEDGEDATE,'MON') = SEARCH -- Unquote variable and use MON not MMM
ORDER BY PAYMONTHS
)
LOOP
DBMS_OUTPUT.PUT_LINE(
'Pledge ID: '||Pledges.IDPLEDGE|| -- Use rowtype variable name not table name.
' Donor ID: '||Pledges.IDDONOR||
' Pledge Amount: '||TO_CHAR(Pledges.PLEDGEAMT)||
' Lump Sum: '||Pledges.MONTHLY_PAYMENT
);
END LOOP;
END;
/
Which, for the sample data:
CREATE TABLE unit_2_assignment( idpledge, iddonor, pledgeamt, pledgedate, paymonths ) AS
SELECT LEVEL,
'Donor' || LEVEL,
LEVEL * 1000,
ADD_MONTHS( DATE '2020-01-01', LEVEL - 1 ),
LEVEL
FROM DUAL
CONNECT BY LEVEL <= 12;
Outputs:
Pledge ID: 1 Donor ID: Donor1 Pledge Amount: 1000 Lump Sum: MONHTLY - 1
You should enclose your substitution variable into single quotes ('&MONTH') because SQLPlus treats it as simple word and can substitute anything, according to examples in so old 8i reference. And it can be figured out by the error message: he tries to use JAN as identifier, so it is not properly enclosed.
Declare
Pledges UNIT_2_ASSIGNMENT%ROWTYPE;
SEARCH DATE;
Begin
SEARCH := '&M0NTH';
What it says:
For example, if the variable SORTCOL has the value JOB and the variable
MYTABLE has the value EMP, SQL*Plus executes the commands
SQL> BREAK ON &SORTCOL
SQL> SELECT &SORTCOL, SAL
2 FROM &MYTABLE
3 ORDER BY &SORTCOL;
But for your task there's no need to use PL/SQL, just format an output of SQLPlus script in appropriate way (have no SQLPlus console to put direct formatting options, but better to read the doc on SQLPlus by yourself).

Having trouble creating trigger that updates column based on variable

I'm trying to create a trigger for a class that updates customer balance depending on how many days late or early the item was returned. I have a charter table that has a due date and return date, the trigger is designed to only fire when the return date is being updated. The trigger then takes the difference between return date and due date and stores that value into a variable. I have a series of if else statements that determine whether the item was returned late or early and then multiply the number of days by the late fee or early bonus. Then it updates the customer balance in the customer table to whatever the value of the fee variable is. Oracle is saying I have a syntax error on my end statement and I'm not sure what is wrong.
CREATE OR REPLACE TRIGGER Fee_Trigger
AFTER UPDATE ON CHARTER
FOR EACH ROW
WHEN ((:NEW.Return_Date <> :OLD.Return_Date AND :NEW.Return_Date IS NOT
NULL))
DECLARE
Fee NUMBER;
BEGIN
Fee := (:NEW.Return_Date - Due_Date);
IF Fee > 0 THEN Fee := (Fee * 75) ;
ELSE IF Fee < 0 THEN Fee := (Fee * 25);
ELSE IF Fee = 0 THEN FEE := Fee;
END IF;
UPDATE CUSTOMER
SET Customer_Balance = Fee
WHERE CustomerID = :NEW.CustomerID
END;
There are some little formatting errors. The following may be used, alternatively :
CREATE OR REPLACE TRIGGER Fee_Trigger
AFTER UPDATE ON CHARTER
FOR EACH ROW
WHEN ((NEW.Return_Date <> OLD.Return_Date AND NEW.Return_Date IS NOT NULL))
DECLARE
Fee NUMBER;
BEGIN
Fee := :NEW.Return_Date - :NEW.Due_Date;
IF Fee > 0 THEN Fee := (Fee * 75);
ELSIF Fee < 0 THEN Fee := (Fee * 25);
ELSIF Fee = 0 THEN Fee := Fee;
END IF;
UPDATE CUSTOMER
SET Customer_Balance = Fee
WHERE CustomerID = :NEW.CustomerID;
END;
The following issues encountered :
Due_date was not defined (:OLD.Due_Date or :NEW.Due_Date may be used)
ELSIF should be used instead of ELSE IF
UPDATE statement should be ended with a semicolon.
Remove colons before OLD and NEW inside WHEN statement.
I suggest replacing the IF/ELSIF statements with a CASE expression in the UPDATE statement:
CREATE OR REPLACE TRIGGER Fee_Trigger
AFTER UPDATE ON CHARTER
FOR EACH ROW
WHEN ((:NEW.Return_Date <> :OLD.Return_Date AND :NEW.Return_Date IS NOT NULL))
DECLARE
Due_Date DATE := TRUNC(SYSDATE); -- initialization as an example value.
nDays_between_return_and_due NUMBER;
BEGIN
nDays_between_return_and_due := TRUNC(:NEW.Return_Date - Due_Date);
UPDATE CUSTOMER
SET Customer_Balance = CASE
WHEN nDays_between_return_and_due > 0 THEN -- Returned late
nDays_between_return_and_due * 75
WHEN nDays_between_return_and_due < 0 THEN -- Returned early
nDays_between_return_and_due * 25
ELSE -- Returned on time
0
END
WHERE CustomerID = :NEW.CustomerID;
END FEE_TRIGGER;
Best of luck.

Why does "WHERE (Time_Stamp >= TDateTime-variable)" ignore fractional seconds?

Using Delphi 6 and Microsoft SQL Server 2000.
I need to extract records where a TDateTime Field is > a passed TDateTime, "FromDate".
It fails as if the fractional part of the seconds of the passed TDateTime are always zero.
Debug printouts confirm that the fractions are there.
The WHERE part ignores the fraction part of :Fdate.
Assume the following 3 records:
Record 1: Time_Stamp is 1.2
Record 2: Time_Stamp is 1.4
Record 3: Time_Stamp is 1.6
The value 1.3 is then sent to the Query in :Fdate.
The resulting dataset returns ALL 3 records.
I expected only records 2 and 3 since 1.3 > 1.2
The 'Time_Stamp' field in database is a SQL 'datetime' field.
Everything works perfectly for integer seconds,
i.e. one record per second, or less often, when the decimal fraction is unimportant.
Can anyone point out where my error is?
The SQL statement is generated by code (shown below) as follows:
SELECT TOP 6 * FROM T_TransactionLog
INNER JOIN T_LookUp_TransTypes
ON T_TransactionLog.TransType = T_LookUp_TransTypes.TransType
WHERE (Time_Stamp >= :Fdate)
AND T_TransactionLog.TransType IN (
3,
4,
5
)
AND LockerNo < 60001
ORDER BY Time_Stamp ASC
The code is as follows:
Query.Connection := Sys_DB_Form.ADOConnection;
DataSource.DataSet := Query;
Query.SQL.Add('SELECT TOP ' + IntToStr(cNoTransactions) + ' * FROM
T_TransactionLog');
Query.SQL.Add('INNER JOIN T_LookUp_TransTypes');
Query.SQL.Add('ON T_TransactionLog.TransType =
T_LookUp_TransTypes.TransType');
Query.SQL.Add('WHERE (Time_Stamp ' + S_Condition + ' :Fdate)');
Query.SQL.Add('AND T_TransactionLog.TransType IN (');
Query.SQL.Add(IntToStr(ord(Apl_TrLog.ttEA)) + ',');
Query.SQL.Add(IntToStr(ord(Apl_TrLog.ttMO)) + ',');
Query.SQL.Add(IntToStr(ord(Apl_TrLog.ttMC)));
Query.SQL.Add(')');
Query.SQL.Add('AND LockerNo < ' +
IntToStr(Apl_Config.cLNoOfFirstgate));
if Locker <> 0 then
begin
Query.SQL.Add('AND LockerNo = ' + IntToStr(Locker));
end;
Query.SQL.Add(S_OrderBy);
Query.Parameters.FindParam('Fdate').Value := FromDate; // <<< Fail????
Query.SQL.SaveToFile(GetApplicationDataPath + 'Sql.txt');
try
Query.Open;
except
ShowMessage('Query open fail on ME Show Transaction log');
end;
Please chech the accuracy note for SQL Server datetime and time data types on MSDN
It is written that:
Accuracy Rounded to increments of .000, .003, or .007 seconds
This means
23:59:59.997
is OK
But
23:59:59.998
will be rounded to 23:59:59.997
And
23:59:59.999
will be rounded to 00:00:00 for the next day