How to show elements from 2 tables ( existing in one , another or both) - sql

I have 2 tables than i need to fuse together for data analysis.
Table One ( shows year consumption of items with values, from a contract)
Table One fields : product code, quantity, total value, contract number
Table Two (shows contract defined included products)
Table Two fields : included product code, included quantity, total included value, contract number
I need to join both of them so that shows per contract, all the related products, both consumed or included, so that shows either i only have consumed but not included, included but not consumed and included and consumed...
Something like this :
Contract|Product Code|Consumed qty|Included Qty|Consumed Total|Included Total
CTC001|X0001|55|45|550|450
CTC001|X0002|20|NULL|200|NULL
CTC001|X0003|NULL|10|NULL|100
CTC002|X0001|10|10|100|100
Using inner join only shows the ones on both tables
Using left or right joins shows all from one table and similar and null's from other table...
My goal was to show from both tables, has the example
Any help or tip ?
(this is my current query, field names not all equal as example, but you get the idea :
SELECT dbo.USR_View_ArtIncludContr.strCodArtigo, dbo.USR_View_TotaisConsumos.strCodArtigo AS Expr2, dbo.USR_View_TotaisConsumos.QTDTOTAL,
dbo.USR_View_ArtIncludContr.fltQuantLimiteInc, dbo.USR_View_TotaisConsumos.VALORTOTAL, dbo.USR_View_ArtIncludContr.Total, dbo.USR_View_TotaisConsumos.strCodSecContrato,
dbo.USR_View_TotaisConsumos.strCodTpContrato, dbo.USR_View_TotaisConsumos.strCodExercContrato, dbo.USR_View_TotaisConsumos.intNumeroContrato, dbo.USR_View_ArtIncludContr.strCodSeccao,
dbo.USR_View_ArtIncludContr.strCodTpContrato AS Expr1, dbo.USR_View_ArtIncludContr.strCodExercicio, dbo.USR_View_ArtIncludContr.intNumero
FROM dbo.USR_View_ArtIncludContr INNER JOIN
dbo.USR_View_TotaisConsumos ON dbo.USR_View_ArtIncludContr.strCodSeccao = dbo.USR_View_TotaisConsumos.strCodSecContrato AND
dbo.USR_View_ArtIncludContr.strCodTpContrato = dbo.USR_View_TotaisConsumos.strCodTpContrato AND
dbo.USR_View_ArtIncludContr.strCodExercicio = dbo.USR_View_TotaisConsumos.strCodExercContrato AND dbo.USR_View_ArtIncludContr.intNumero = dbo.USR_View_TotaisConsumos.intNumeroContrato AND
dbo.USR_View_ArtIncludContr.strCodArtigo = dbo.USR_View_TotaisConsumos.strCodArtigo

Sounds like you want a full join:
SELECT aic.strCodArtigo, tc.strCodArtigo AS Expr2, tc.QTDTOTAL,
aic.fltQuantLimiteInc, tc.VALORTOTAL, aic.Total, tc.strCodSecContrato,
tc.strCodTpContrato, tc.strCodExercContrato, tc.intNumeroContrato, aic.strCodSeccao,
aic.strCodTpContrato AS Expr1, aic.strCodExercicio, aic.intNumero
FROM dbo.USR_View_ArtIncludContr aic FULL JOIN
dbo.USR_View_TotaisConsumos tc
ON aic.strCodSeccao = tc.strCodSecContrato AND
aic.strCodTpContrato = tc.strCodTpContrato AND
aic.strCodExercicio = tc.strCodExercContrato AND
aic.intNumero = tc.intNumeroContrato AND
aic.strCodArtigo = tc.strCodArtigo
Notice that column aliases make the query much easier to write and to read.

Just figure out an workaround...
i could use CASE WHEN for the contract and for product code...
Something like this in select :
"CASE WHEN AIC.strCodArtigo IS NULL THEN TC.strCodArtigo WHEN TC.strCodArtigo IS NULL THEN AIC.strCodArtigo ELSE AIC.strCodArtigo END AS ARTIGO "
And use FULL OUTER JOIN
In case anyone has a better way, i appreciate any opinion

Related

Should I use an SQL full outer join for this?

Consider the following tables:
Table A:
DOC_NUM
DOC_TYPE
RELATED_DOC_NUM
NEXT_STATUS
...
Table B:
DOC_NUM
DOC_TYPE
RELATED_DOC_NUM
NEXT_STATUS
...
The DOC_TYPE and NEXT_STATUS columns have different meanings between the two tables, although a NEXT_STATUS = 999 means "closed" in both. Also, under certain conditions, there will be a record in each table, with a reference to a corresponding entry in the other table (i.e. the RELATED_DOC_NUM columns).
I am trying to create a query that will get data from both tables that meet the following conditions:
A.RELATED_DOC_NUM = B.DOC_NUM
A.DOC_TYPE = "ST"
B.DOC_TYPE = "OT"
A.NEXT_STATUS < 999 OR B.NEXT_STATUS < 999
A.DOC_TYPE = "ST" represents a transfer order to transfer inventory from one plant to another. B.DOC_TYPE = "OT" represents a corresponding receipt of the transferred inventory at the receiving plant.
We want to get records from either table where there is an ST/OT pair where either or both entries are not closed (i.e. NEXT_STATUS < 999).
I am assuming that I need to use a FULL OUTER join to accomplish this. If this is the wrong assumption, please let me know what I should be doing instead.
UPDATE (11/30/2021):
I believe that #Caius Jard is correct in that this does not need to be an outer join. There should always be an ST/OT pair.
With that I have written my query as follows:
SELECT <columns>
FROM A LEFT JOIN B
ON
A.RELATED_DOC_NUM = B.DOC_NUM
WHERE
A.DOC_TYPE IN ('ST') AND
B.DOC_TYPE IN ('OT') AND
(A.NEXT_STATUS < 999 OR B.NEXT_STATUS < 999)
Does this make sense?
UPDATE 2 (11/30/2021):
The reality is that these are DB2 database tables being used by the JD Edwards ERP application. The only way I know of to see the table definitions is by using the web site http://www.jdetables.com/, entering the table ID and hitting return to run the search. It comes back with a ton of information about the table and its columns.
Table A is really F4211 and table B is really F4311.
Right now, I've simplified the query to keep it simple and keep variables to a minimum. This is what I have currently:
SELECT CAST(F4211.SDDOCO AS VARCHAR(8)) AS SO_NUM,
F4211.SDRORN AS RELATED_PO,
F4211.SDDCTO AS SO_DOC_TYPE,
F4211.SDNXTR AS SO_NEXT_STATUS,
CAST(F4311.PDDOCO AS VARCHAR(8)) AS PO_NUM,
F4311.PDRORN AS RELATED_SO,
F4311.PDDCTO AS PO_DOC_TYPE,
F4311.PDNXTR AS PO_NEXT_STATUS
FROM PROD2DTA.F4211 AS F4211
INNER JOIN PROD2DTA.F4311 AS F4311
ON F4211.SDRORN = CAST(F4311.PDDOCO AS VARCHAR(8))
WHERE F4211.SDDCTO IN ( 'ST' )
AND F4311.PDDCTO IN ( 'OT' )
The other part of the story is that I'm using a reporting package that allows you to define "virtual" views of the data. Virtual views allow the report developer to specify the SQL to use. This is the application where I am using the SQL. When I set up the SQL, there is a validation step that must be performed. It will return a limited set of results if the SQL is validated.
When I enter the query above and validate it, it says that there are no results, which makes no sense. I'm guessing the data casting is causing the issue, but not sure.
UPDATE 3 (11/30/2021):
One more twist to the story. The related doc number is not only defined as a string value, but it contains leading zeros. This is true in both tables. The main doc number (in both tables) is defined as a numeric value and therefore has no leading zeros. I have no idea why those who developed JDE would have done this, but that is what is there.
So, there are matching records between the two tables that meet the criteria, but I think I'm getting no results because when I convert the numeric to a string, it does not match, because one value is, say "12345", while the other is "00012345".
Can I pad the numeric -> string value with zeros before doing the equals check?
UPDATE 4 (12/2/2021):
Was able to finally get the query to work by converting the numeric doc num to a left zero padded string.
SELECT <columns>
FROM PROD2DTA.F4211 AS F4211
INNER JOIN PROD2DTA.F4311 AS F4311
ON F4211.SDRORN = RIGHT(CONCAT('00000000', CAST(F4311.PDDOCO AS VARCHAR(8))), 8)
WHERE F4211.SDDCTO IN ( 'ST' )
AND F4311.PDDCTO IN ( 'OT' )
AND ( F4211.SDNXTR < 999
OR F4311.PDNXTR < 999 )
You should write your query as follows:
SELECT <columns>
FROM A INNER JOIN B
ON
A.RELATED_DOC_NUM = B.DOC_NUM
WHERE
A.DOC_TYPE IN ('ST') AND
B.DOC_TYPE IN ('OT') AND
(A.NEXT_STATUS < 999 OR B.NEXT_STATUS < 999)
LEFT join is a type of OUTER join; LEFT JOIN is typically a contraction of LEFT OUTER JOIN). OUTER means "one side might have nulls in every column because there was no match". Most critically, the code as posted in the question (with a LEFT JOIN, but then has WHERE some_column_from_the_right_table = some_value) runs as an INNER join, because any NULLs inserted by the LEFT OUTER process, are then quashed by the WHERE clause
See Update 4 for details of how I resolved the "data conversion or mapping" error.

SQL - join three tables based on (different) latest dates in two of them

Using Oracle SQL Developer, I have three tables with some common data that I need to join.
Appreciate any help on this!
Please refer to https://i.stack.imgur.com/f37Jh.png for the input and desired output (table formatting doesn't work on all tables).
These tables are made up in order to anonymize them, and in reality contain other data with millions of entries, but you could think of them as representing:
Product = Main product categories in a grocery store.
Subproduct = Subcategory products to the above. Each time the table is updated, the main product category may loses or get some new suproducts assigned to it. E.g. you can see that from May to June the Pulled pork entered while the Fishsoup was thrown out.
Issues = Status of the products, for example an apple is bad if it has brown spots on it..
What I need to find is: for each P_NAME, find the latest updated set of subproducts (SP_ID and SP_NAME), and append that information with the latest updated issue status (STATUS_FLAG).
Please note that each main product category gets its set of subproducts updated at individual occasions i.e. 1234 and 5678 might be "latest updated" on different dates.
I have tried multiple queries but failed each time. I am using combos of SELECT, LEFT OUTER JOIN, JOIN, MAX and GROUP BY.
Latest attempt, which gives me the combo of the first two tables, but missing the third:
SELECT
PRODUCT.P_NAME,
SUBPRODUCT.SP_PRODUCT_ID, SUBPRODUCT.SP_NAME, SUBPRODUCT.SP_ID, SUPPRODUCT.SP_VALUE_DATE
FROM SUBPRODUCT
LEFT OUTER JOIN PRODUCT ON PRODUCT.P_ID = SUBPRODUCT.SP_PRODUCT_ID
JOIN(SELECT SP_PRODUCT_ID, MAX(SP_VALUE_DATE) AS latestdate FROM SUBPRODUCT GROUP BY SP_PRODUCT_ID) sub ON
sub.SP_PRODUCT_ID = SUBPRODUCT.SP_PRODUCT_ID AND sub.latestDate = SUBPRODUCT.SP_VALUE_DATE;
Trying to find a row with a max value is a common SQL pattern - you can do it with a join, like your example, but it's usually more clear to use a subquery or a window function.
Correlated subquery example
select
PRODUCT.P_NAME,
SUBPRODUCT.SP_PRODUCT_ID, SUBPRODUCT.SP_NAME, SUBPRODUCT.SP_ID, SUPPRODUCT.SP_VALUE_DATE,
ISSUES.STATUS_FLAG, ISSUES.STATUS_LAST_UPDATED
from PRODUCT
join SUBPRODUCT
on PRODUCT.P_ID = SUBPRODUCT.SP_PRODUCT_ID
and SUBPRODUCT.SP_VALUE_DATE = (select max(S2.SP_VALUE_DATE) as latestDate
from SUBPRODUCT S2
where S2.SP_PRODUCT_ID = SUBPRODUCT.SP_PRODUCT_ID)
join ISSUES
on ISSUES.ISSUE_ID = SUBPRODUCT.SP_ID
and ISSUES.STATUS_LAST_UPDATED = (select max(I2.STATUS_LAST_UPDATED) as latestDate
from ISSUES I2
where I2.ISSUE_ID = ISSUES.ISSUE_ID)
Window function / inline view example
select
PRODUCT.P_NAME,
S.SP_PRODUCT_ID, S.SP_NAME, S.SP_ID, S.SP_VALUE_DATE,
I.STATUS_FLAG, I.STATUS_LAST_UPDATED
from PRODUCT
join (select SUBPRODUCT.*,
max(SP_VALUE_DATE) over (partition by SP_PRODUCT_ID) as latestDate
from SUBPRODUCT) S
on PRODUCT.P_ID = S.SP_PRODUCT_ID
and S.SP_VALUE_DATE = S.latestDate
join (select ISSUES.*,
max(STATUS_LAST_UPDATED) over (partition by ISSUE_ID) as latestDate
from ISSUES) I
on I.ISSUE_ID = S.SP_ID
and I.STATUS_LAST_UPDATED = I.latestDate
This often performs a bit better, but window functions can be tricky to understand.

OracleAPPS- Can not get correct results for Suppliers - Bank query

I am trying to fetch suppliers and bank details in Oracle apps. I am able to write a simple query where each supplier has a supplier site attached to it. Few of my sites doesn't have a record in table "iby_pmt_instr_uses_all". But even then I want to show them . So I am using the outer join on this table. But the issue is when I am putting this outer join condition, I am getting double the records in the query. I believe I am missing on some condition, but can not figure out which one.
SELECT *
FROM apps.iby_pmt_instr_uses_all instrument,
apps.iby_account_owners owners,
apps.iby_external_payees_all payees,
apps.iby_ext_bank_accounts ieb,
apps.ap_supplier_sites_all asa,
apps.ap_suppliers asp,
apps.ce_bank_branches_v cbbv
WHERE owners.ext_bank_account_id = ieb.ext_bank_account_id
AND owners.ext_bank_account_id = instrument.instrument_id(+)
AND payees.ext_payee_id = instrument.ext_pmt_party_id(+)
AND cbbv.branch_party_id = ieb.branch_id
AND payees.payee_party_id = owners.account_owner_party_id
AND payees.supplier_site_id = asa.vendor_site_id
AND asa.vendor_id = asp.vendor_id
AND asp.vendor_name = 'PANALYTICAL'
--and ieb.bank_account_num = asa.VENDOR_SITE_CODE
If I add and ieb.bank_account_num = asa.VENDOR_SITE_CODE this condition I get the correct record, but actually this is not the right join, because there is no relationship between these 2 columns, so this will fail for other suppliers.
Can you please suggest what additional join I can put , so that I get the right result.
Thanks

SQL - getting data twice from the same table

Good people of the internet, I need your help!
I'm trying to put together some SQL code to create a report. Basically, I'm needing to look at one table - tbl_Schedules - and fetch the maximum of the field SchedDone, which is a regular date field.
This is fair enough. I manage this using GROUP BY and MAX.
The same table also contains SchedFrom and SchedTo fields, and I need to get this from another record, but run alongside this.
Basically, I need a "LatestDate" field (which shows the max SchedDone), and then a "next scheduled" field (or fields), showing when it is next to be done, pulled from a row where the SchedDone is null.
My current code, displayed below (ignore everything but the tbl_Schedules stuff) is working to an extent. It shows the LatestDate as described above, but also shows the maximum of that Task's SchedFrom and SchedTo. These are all from different rows in the tbl_Schedules, which is what I want. I just need to know how to set up rules for the SchedFrom and SchedTo, preferably without involving any other tables or setting up multiple views.
I do have this working, but it's taking up several views and the speed involved is not good. I'd hope I can get it working in a single chunk of SQL code.
PS - tbl_PhysicalAssets is a one-to-many relationship with tbl_Operations (one row in tbl_PhysicalAssets to many in tbl_Operations), and tbl_Operations is a one-to-many relationship with tbl_Schedules (one row in tbl_Operations to many in tbl_Schedules).
Current code below (again, please ignore the other tables!) -
SELECT
dbo.tbl_PhysicalAsset.FKID_Contract,
dbo.tbl_PhysicalAsset.MyLevel,
dbo.tbl_PhysicalAsset.L1_Name,
dbo.tbl_PhysicalAsset.L2_Name,
dbo.tbl_PhysicalAsset.L3_Name,
dbo.tbl_OpList.Operation_Name,
dbo.tbl_Teams.Team_Name,
MAX(tbl_Schedules_1.SchedDone) AS LatestDate,
MAX(tbl_Schedules_1.SchedFrom) AS Expr1,
MAX(tbl_Schedules_1.SchedTo) AS Expr2
FROM
dbo.tbl_Schedules AS tbl_Schedules_1
RIGHT OUTER JOIN
dbo.tbl_PhysicalAsset
INNER JOIN
dbo.tbl_Operations ON dbo.tbl_PhysicalAsset.PKID_PhysicalAsset = dbo.tbl_Operations.FKID_PhysicalAsset
INNER JOIN
dbo.tbl_OpList ON dbo.tbl_Operations.FKID_Operation = dbo.tbl_OpList.PKID_Op
INNER JOIN
dbo.tbl_Teams ON dbo.tbl_Operations.FKID_Team = dbo.tbl_Teams.PKID_Team ON tbl_Schedules_1.FKID_Operation = dbo.tbl_Operations.PKID_Operation
GROUP BY
dbo.tbl_PhysicalAsset.FKID_Contract,
dbo.tbl_PhysicalAsset.MyLevel,
dbo.tbl_PhysicalAsset.L1_Name,
dbo.tbl_PhysicalAsset.L2_Name,
dbo.tbl_PhysicalAsset.L3_Name,
dbo.tbl_OpList.Operation_Name,
dbo.tbl_Teams.Team_Name
HAVING
(dbo.tbl_PhysicalAsset.FKID_Contract = 6)
AND (dbo.tbl_PhysicalAsset.MyLevel = 3)
This is rough as we don't know the exact details of your table structure.
But basically you need to first write the queries that get the two separate bits of information, make sure they work in isolation. You can then just join them together.
So something like (I've assumed FKID_Operation is the 'common' piece of info):
select
a.FKID_Operation
, b.LatestDate
, c.NextToDate
, c.NextFromDate
from tbl_Schedules a
inner join
(
select
m.FKID_Operation
, Max(m.SchedDone) as LatestDate
from tbl_Schedules m
where SchedDone is not null
) b
on a.FKID_Operation = b.FKID_Operation
inner join
(
select
n.FKID_Operation
, n.SchedTo as NextToDate
, n.SchedFrom as NextFromDate
from tbl_Schedules n
where SchedDone is null
) c
on a.FKID_Operation = c.FKID_Operation
I'd also look into CTE's as they can make this kind of query much easier to understand.

Include missing years in Group By query

I am fairly new in Access and SQL programming. I am trying to do the following:
Sum(SO_SalesOrderPaymentHistoryLineT.Amount) AS [Sum Of PaymentPerYear]
and group by year even when there is no amount in some of the years. I would like to have these years listed as well for a report with charts. I'm not certain if this is possible, but every bit of help is appreciated.
My code so far is as follows:
SELECT
Base_CustomerT.SalesRep,
SO_SalesOrderT.CustomerId,
Base_CustomerT.Customer,
SO_SalesOrderPaymentHistoryLineT.DatePaid,
Sum(SO_SalesOrderPaymentHistoryLineT.Amount) AS [Sum Of PaymentPerYear]
FROM
Base_CustomerT
INNER JOIN (
SO_SalesOrderPaymentHistoryLineT
INNER JOIN SO_SalesOrderT
ON SO_SalesOrderPaymentHistoryLineT.SalesOrderId = SO_SalesOrderT.SalesOrderId
) ON Base_CustomerT.CustomerId = SO_SalesOrderT.CustomerId
GROUP BY
Base_CustomerT.SalesRep,
SO_SalesOrderT.CustomerId,
Base_CustomerT.Customer,
SO_SalesOrderPaymentHistoryLineT.DatePaid,
SO_SalesOrderPaymentHistoryLineT.PaymentType,
Base_CustomerT.IsActive
HAVING
(((SO_SalesOrderPaymentHistoryLineT.PaymentType)=1)
AND ((Base_CustomerT.IsActive)=Yes))
ORDER BY
Base_CustomerT.SalesRep,
Base_CustomerT.Customer;
You need another table with all years listed -- you can create this on the fly or have one in the db... join from that. So if you had a table called alltheyears with a column called y that just listed the years then you could use code like this:
WITH minmax as
(
select min(year(SO_SalesOrderPaymentHistoryLineT.DatePaid) as minyear,
max(year(SO_SalesOrderPaymentHistoryLineT.DatePaid) as maxyear)
from SalesOrderPaymentHistoryLineT
), yearsused as
(
select y
from alltheyears, minmax
where alltheyears.y >= minyear and alltheyears.y <= maxyear
)
select *
from yearsused
join ( -- your query above goes here! -- ) T
ON year(T.SO_SalesOrderPaymentHistoryLineT.DatePaid) = yearsused.y
You need a data source that will provide the year numbers. You cannot manufacture them out of thin air. Supposing you had a table Interesting_year with a single column year, populated, say, with every distinct integer between 2000 and 2050, you could do something like this:
SELECT
base.SalesRep,
base.CustomerId,
base.Customer,
base.year,
Sum(NZ(data.Amount)) AS [Sum Of PaymentPerYear]
FROM
(SELECT * FROM Base_CustomerT INNER JOIN Year) AS base
LEFT JOIN
(SELECT * FROM
SO_SalesOrderT
INNER JOIN SO_SalesOrderPaymentHistoryLineT
ON (SO_SalesOrderPaymentHistoryLineT.SalesOrderId = SO_SalesOrderT.SalesOrderId)
) AS data
ON ((base.CustomerId = data.CustomerId)
AND (base.year = Year(data.DatePaid))),
WHERE
(data.PaymentType = 1)
AND (base.IsActive = Yes)
AND (base.year BETWEEN
(SELECT Min(year(DatePaid) FROM SO_SalesOrderPaymentHistoryLineT)
AND (SELECT Max(year(DatePaid) FROM SO_SalesOrderPaymentHistoryLineT))
GROUP BY
base.SalesRep,
base.CustomerId,
base.Customer,
base.year,
ORDER BY
base.SalesRep,
base.Customer;
Note the following:
The revised query first forms the Cartesian product of BaseCustomerT with Interesting_year in order to have base customer data associated with each year (this is sometimes called a CROSS JOIN, but it's the same thing as an INNER JOIN with no join predicate, which is what Access requires)
In order to have result rows for years with no payments, you must perform an outer join (in this case a LEFT JOIN). Where a (base customer, year) combination has no associated orders, the rest of the columns of the join result will be NULL.
I'm selecting the CustomerId from Base_CustomerT because you would sometimes get a NULL if you selected from SO_SalesOrderT as in the starting query
I'm using the Access Nz() function to convert NULL payment amounts to 0 (from rows corresponding to years with no payments)
I converted your HAVING clause to a WHERE clause. That's semantically equivalent in this particular case, and it will be more efficient because the WHERE filter is applied before groups are formed, and because it allows some columns to be omitted from the GROUP BY clause.
Following Hogan's example, I filter out data for years outside the overall range covered by your data. Alternatively, you could achieve the same effect without that filter condition and its subqueries by ensuring that table Intersting_year contains only the year numbers for which you want results.
Update: modified the query to a different, but logically equivalent "something like this" that I hope Access will like better. Aside from adding a bunch of parentheses, the main difference is making both the left and the right operand of the LEFT JOIN into a subquery. That's consistent with the consensus recommendation for resolving Access "ambiguous outer join" errors.
Thank you John for your help. I found a solution which works for me. It looks quiet different but I learned a lot out of it. If you are interested here is how it looks now.
SELECT DISTINCTROW
Base_Customer_RevenueYearQ.SalesRep,
Base_Customer_RevenueYearQ.CustomerId,
Base_Customer_RevenueYearQ.Customer,
Base_Customer_RevenueYearQ.RevenueYear,
CustomerPaymentPerYearQ.[Sum Of PaymentPerYear]
FROM
Base_Customer_RevenueYearQ
LEFT JOIN CustomerPaymentPerYearQ
ON (Base_Customer_RevenueYearQ.RevenueYear = CustomerPaymentPerYearQ.[RevenueYear])
AND (Base_Customer_RevenueYearQ.CustomerId = CustomerPaymentPerYearQ.CustomerId)
GROUP BY
Base_Customer_RevenueYearQ.SalesRep,
Base_Customer_RevenueYearQ.CustomerId,
Base_Customer_RevenueYearQ.Customer,
Base_Customer_RevenueYearQ.RevenueYear,
CustomerPaymentPerYearQ.[Sum Of PaymentPerYear]
;