How to combine multiple complex queries? - sql

There is a query that displays data by id (R_PERS_ACCOUNT_ID) and date (MAX(RBS.CREATE_DATE))
Select rpao.r_pers_account_id, max(rbs.create_date)
from r_base_trans rbs
join r_pers_acc_operation rpao on rbs.r_base_trans_id = rpao.r_base_trans_id
where rbs.create_date between to_date('01.12.2017', 'dd.mm.yyyy') and to_date('31.12.2020', 'dd.mm.yyyy')
and rbs.M_BASE_TRANS_TYPE_ID NOT IN 26
and ROWNUM < 100
group by rpao.r_pers_account_id;
enter image description here
There is one more request in which you need to insert data from the previous select. In the where clause where pa.r_pers_account_id, you need to insert the id from the previous table. And in to_date('31-01-2018', 'dd-mm-yyyy') there is also date data from the previous table. (In my case, I manually inserted only one data)
select TP.IIN_BIN,
pa.r_pers_account_id,
pa.close_date,
kbk.kbk_code,
org.code_nk,
org.CODE_TPK,
op.m_operation_type_id,
pa.open_date,
sum(op.amount)
from r_pers_account pa
join r_tax_payer tp on pa.r_tax_payer_id = tp.r_tax_payer_id
join r_pers_acc_operation op on op.r_pers_account_id = pa.r_pers_account_id
join m_kbk kbk on kbk.m_kbk_id = pa.m_kbk_id
join m_tax_org org on org.m_tax_org_id = pa.m_tax_org_id
where pa.r_pers_account_id in (16616864)
and is_charge_fine = 0
and trunc(op.actual_date, 'fmdd') <= to_date('31-01-2018', 'dd-mm-yyyy')
and op.m_operation_type_id = 1
group by tp.IIN_BIN, pa.r_pers_account_id, pa.close_date, kbk.kbk_code, op.m_operation_type_id, org.code_nk,
org.code_tpk, pa.open_date;
enter image description here
In this select, you also need to insert data by id and date.
select TP.IIN_BIN,
pa.r_pers_account_id,
pa.close_date,
kbk.kbk_code,
org.code_nk,
org.CODE_TPK,
op.m_operation_type_id,
pa.open_date,
sum(op.amount)
from r_pers_account pa
join r_tax_payer tp on pa.r_tax_payer_id = tp.r_tax_payer_id
join r_pers_acc_operation op on op.r_pers_account_id = pa.r_pers_account_id
join m_kbk kbk on kbk.m_kbk_id = pa.m_kbk_id
join m_tax_org org on org.m_tax_org_id = pa.m_tax_org_id
where pa.r_pers_account_id in (16616864)
and is_charge_fine = 0
and trunc(op.actual_date, 'fmdd') <= to_date('31-01-2018', 'dd-mm-yyyy')
and op.m_operation_type_id = 2
group by tp.IIN_BIN, pa.r_pers_account_id, pa.close_date, kbk.kbk_code, op.m_operation_type_id, org.code_nk,
org.code_tpk, pa.open_date;
enter image description here
It is necessary to make so that these 3 requests were one select.
In addition, after combining these queries, you need to display data by condition if the second select column sum(op.amount) has a negative number, and the third select column sum(op.amount) has 0 or a positive number

I don't quite understand what queries you posted do (2nd and 3rd look just the same to me), but - generally speaking - if you want to "reuse" one query in queries that follow, there's a useful option: CTE (common table expression, i.e. the WITH factoring clause).
Simplified, it would look like this; I hope you'll manage to apply it to your code:
with
first_query as
(select rpao.r_pers_account_id, ...
from ...
where ...
),
second_query as
(select tp.iin_bin, ...
from FIRST_QUERY f1 join r_per_account pa on ...
--------------
-- this is new!
join ...
where ...
),
third_query as
(select tp.iin_bin, ...
from ...
-- use SECOND_QUERY (and/or FIRST_QUERY, if you have to)
where ...
)
-- Finally: extract data you really need
select ...
from third_query t3
where ...

Related

How to Get a Count of Records Using Partitioning in Oracle

I have the following query:
SELECT
F.IID,
F.E_NUM AS M_E_NUM,
MCI.E_NUM AS MCI_E_NUM,
F.C_NUM AS M_C_NUM,
MCI.C_NUM AS MCI_C_NUM,
F.ET_ID AS M_ET_ID,
EDIE.ET_ID AS ED_INDV_ET_ID,
COUNT(*) OVER (PARTITION BY F.IID) IID_COUNT
FROM FT_T F JOIN CEMEI_T MCI ON F.IID = MCI.IID
JOIN EDE_T EDE ON MCI.E_NUM = EDE.E_NUM
JOIN EDIE_T EDIE ON EDIE.IID = F.IID AND EDIE.ET_ID = EDE.ET_ID
WHERE
F.DEL_F = 'N'
AND MCI.EFF_END_DT IS NULL
AND MCI.TOS = 'BVVB'
AND EDE.PTEND_DT IS NULL
AND EDE.DEL_S = 'N'
AND EDE.CUR_IND = 'A'
AND EDIE.TAR_N = 'Y'
AND F.IID IN
(
SELECT DISTINCT IID
FROM FT_T
WHERE GROUP_ID = 'BG'
AND DEL_F = 'N'
AND (IID, E_NUM) NOT IN
(
SELECT IID, E_NUM FROM CEMEI_T
WHERE TOS = 'BVVB' AND EFF_END_DT IS NULL
)
);
I am basically grabbing information from several tables and creating a flat record of them.
Everything works accordingly except now I need to find out whether there are two records in FT_T table with identical IID's and display that count as part of the result set.
I tried to use partitioning but all the rows in the result set return a single count even though there are ones that have 2 records with identical IID's in FT_T.
The reason I initially said that I'm gathering information from several tables is due to the fact that FT_T might not have all the information I need if two records are not available for the same IID, so I have to retrieve them from other tables JOINed in the query. However, I need to know which FT_T.IID's have two records in FT_T (or greater than one).
Perhaps you need to calculate the count before the join and filtering:
SELECT . . .
FROM (SELECT F.*,
COUNT(*) OVER (PARTITION BY F.IID) as IID_CNT
FROM FT_T F
) JOIN
CEMEI_T MCI
ON F.IID = MCI.IID JOIN
EDE_T EDE
ON MCI.E_NUM = EDE.E_NUM JOIN
EDIE_T EDIE
ON EDIE.IID = F.IID AND EDIE.ET_ID = EDE.ET_ID
. . .
this is merely a comment/observation, but formatting is needed
You use of in(...) with select distinct and not in(...,...) seems complex and could be a problem if some values are NULL. I suggest you consider using EXISTS and NOT EXISTS instead. e.g.
AND EXISTS (
SELECT
NULL
FROM FT_T
WHERE F.IID = FT_T.IID
AND FT_T.GROUP_ID = 'BG'
AND FT_T.DEL_F = 'N'
AND NOT EXISTS (
SELECT
NULL
FROM CEMEI_T
WHERE FT_T.IID = CEMEI_T.IID
AND FT_T.E_NUM = CEMEI_T.E_NUM
AND CEMEI_T.TOS = 'BVVB'
AND CEMEI_T.EFF_END_DT IS NULL
)
)

where statement execute before inner join

I'm trying to grab the first instance of each result with a sysAddress of less than 4. However my statement currently grabs the min(actionTime) result first before applying the where sysAddress < 4. I'm trying to have the input for the inner join as the where sysAddress < 4 however i cant seem to figure out how to do it.
Should i be nesting it all differently? I didnt want to create an additional layer of table joins. Is this possible? I'm a bit lost at all the answers ive found.
SELECT
tblHistoryObject.info,
tblHistory.actionTime,
tblHistoryUser.userID,
tblHistoryUser.firstName,
tblHistoryUser.surname,
tblHistory.eventID,
tblHistoryObject.objectID,
tblHistorySystem.sysAddress
FROM tblHistoryObject
JOIN tblHistory
ON (tblHistory.historyObjectID = tblHistoryObject.historyObjectID)
JOIN tblHistorySystem
ON (tblHistory.historySystemID = tblHistorySystem.historySystemID)
JOIN tblHistoryUser
ON (tblHistory.historyUserID = tblHistoryUser.historyUserID)
INNER JOIN (SELECT
MIN(actionTime) AS recent_date,
historyObjectID
FROM tblHistory
GROUP BY historyObjectID) AS t2
ON t2.historyObjectID = tblHistoryObject.historyObjectID
AND tblHistory.actionTime = t2.recent_date
WHERE sysAddress < 4
ORDER BY actionTime ASC
WITH
all_action_times AS
(
SELECT
tblHistoryObject.info,
tblHistory.actionTime,
tblHistoryUser.userID,
tblHistoryUser.firstName,
tblHistoryUser.surname,
tblHistory.eventID,
tblHistoryObject.objectID,
tblHistorySystem.sysAddress,
ROW_NUMBER() OVER (PARTITION BY tblHistoryObject.historyObjectID
ORDER BY tblHistory.actionTime
)
AS historyObjectID_SeqByActionTime
FROM
tblHistoryObject
INNER JOIN
tblHistory
ON tblHistory.historyObjectID = tblHistoryObject.historyObjectID
INNER JOIN
tblHistorySystem
ON tblHistory.historySystemID = tblHistorySystem.historySystemID
INNER JOIN
tblHistoryUser
ON tblHistory.historyUserID = tblHistoryUser.historyUserID
WHERE
tblHistorySystem.sysAddress < 4
)
SELECT
*
FROM
all_action_times
WHERE
historyObjectID_SeqByActionTime = 1
ORDER BY
actionTime ASC
This does exactly what your original query did, without trying to filter by action_time.
Then it appends a new column, using ROW_NUMBER() to generate sequences from 1 for each individual tblHistoryObject.historyObjectID. Then it takes only the rows where this sequence value is 1 (the first row per historyObjectID, when sorted in action_time order).

SQL Query returning multiple Duplicate Results

scenario : I have Three Tables(Prisoners,AddPaymentTransaction,WithdrawPaymentTransation)
Date in Tables : i have 1 row of prisoner with PrisonerID=5 and two rows in both other table,
i have wrote query to return there data if any prisoner have add some payment in there account or with draw any payment from there payment on same day or on different dates etc.
here is my query :
select at.PrisonerID ,at.Amount as AAmount,at.Date as ADate,wt.Amount as WAmount,wt.Date as WDate
from Prisoners p, AddPaymentTransaction at,WithdrawPaymentTransation wt
where p.PrisonerID=at.PrisonerID and p.PrisonerID=wt.PrisonerID and at.PrisonerID=wt.PrisonerID and at.PrisonerID=5
but it gives me 4 rows, 9 rows when i have 3 rows of data in each Table etc.
i want rows of data with out duplicate. any suggestions or help will be highly appreciated.
It looks like at.PrisonerID = wt.PrisonerID in your query might be what is causing all of the duplicates. I am guessing AddPaymentTransaction and WithdrawPaymentTransation should not be linked together. So, how about the following:
SELECT at.PrisonerID, at.Amount as AAmount, at.Date as ADate,
wt.Amount as WAmount, wt.Date as WDate
FROM Prisoners p
INNER JOIN AddPaymentTransaction at p.PrisonerID = at.PrisonerID
INNER JOIN WithdrawPaymentTransation wt ON p.PrisonerID = wt.PrisonerID
WHERE at.PrisonerID = 5
but this probably isn't going to give you exactly what you are looking for either. So maybe something like the following:
SELECT * FROM
(
SELECT p.PrisonerID, 'AddPayment' AS Type,
apt.Amount as TransAmount, apt.Date AS TransDate
FROM Prisoners p
INNER JOIN AddPaymentTransaction apt ON p.PrisonerID = apt.PrisonerID
WHERE apt.PrisonerID = 5
UNION
SELECT p.PrisonerID, 'WithdrawPayment' AS Type,
wt.Amount as TransAmount, wt.Date as TransDate
FROM Prisoners p
INNER JOIN WithdrawPaymentTransation wt ON p.PrisonerID = wt.PrisonerID
WHERE wt.PrisonerID = 5
) AS mq
ORDER BY mq.TransDate DESC

SQL Selecting based off largest date from different table

I am attempting to write a query that pulls Order information from various tables. I have hit a road block at the target date value.
It seems that every time a target date is changed a new row is added in that table. All I want is to be able to select only the newest Target Date. What should I do?
select Distinct
OR01001 AS OrderNumber,
OR01002 AS OrderType,
OR01003 AS CustomerCode,
OR01015 AS OrderDate,
OR01017 AS CustomerREP,
OR01018 AS ContactPerson,
OR01019 AS SalesmanNumber,
OR03011 - OR03012 AS OpenQuantity,
SC03003 AS StockBalance,
OR01050 AS WarehouseNumber,
OR01072 AS CustomerPO,
OR03005 AS ItemCode,
OR03002 AS LineNumber,
OR500100.OR50004 As TargetDate
from OR010100
INNER Join OR030100 ON OR030100.OR03001 = OR010100.OR01001
INNER Join SL010100 ON SL010100.SL01001 = OR010100.OR01003
INNER Join SC030100 ON SC030100.SC03001 = OR030100.OR03005
Inner JOIN OR500100 ON OR500100.OR50001 = OR010100.OR01001
where OR010100.OR01002 <> 0 AND OR010100.OR01002 <> 6 AND OR01017 = 'SLOTT'
Order by OR01017 ASC;
If I understand your columns correctly, here's one way:
SELECT ...,
OR500100A.OR50004 AS TargetDate
FROM ...
INNER JOIN OR500100 AS OR500100A ON OR500100A.OR50001 = OR010100.OR01001
AND NOT EXISTS(SELECT 1 FROM OR500100 AS OR500100B
WHERE OR500100B.OR5001 = OR010100.OR01001
AND OR500100B.OR50004 > OR500100A.OR50004)
...
This makes sure you only get one OR500100 row with the latest value in OR50004 for the given OR5001.
from what i understand,
SELECT
...
MAX(OR500100.OR50004) As TargetDate
FROM...
WHERE...
GROUP BY --everything but OR500100.OR50004
ORDER BY...
should do the trick
EDIT: ty Ic.

SQL - Derived tables issue

I have the following SQL query:
SELECT VehicleRegistrations.ID, VehicleRegistrations.VehicleReg,
VehicleRegistrations.Phone, VehicleType.VehicleTypeDescription,
dt.ID AS 'CostID', dt.IVehHire, dt.FixedCostPerYear, dt.VehicleParts,
dt.MaintenancePerMile, dt.DateEffective
FROM VehicleRegistrations
INNER JOIN VehicleType ON VehicleRegistrations.VehicleType = VehicleType.ID
LEFT OUTER JOIN (SELECT TOP (1) ID, VehicleRegID, DateEffective, IVehHire,
FixedCostPerYear, VehicleParts, MaintenancePerMile
FROM VehicleFixedCosts
WHERE (DateEffective <= GETDATE())
ORDER BY DateEffective DESC) AS dt
ON dt.VehicleRegID = VehicleRegistrations.ID
What I basically want to do is always select the top 1 record from the 'VehicleFixedCosts' table, where the VehicleRegID matches the one in the main query. What is happening here is that it's selecting the top row before the join, so if the vehicle registration of the top row doesn't match the one we're joining to it returns nothing.
Any ideas? I really don't want to have use subselects for each of the columns I need to return
Try this:
SELECT vr.ID, vr.VehicleReg,
vr.Phone, VehicleType.VehicleTypeDescription,
dt.ID AS 'CostID', dt.IVehHire, dt.FixedCostPerYear, dt.VehicleParts,
dt.MaintenancePerMile, dt.DateEffective
FROM VehicleRegistrations vr
INNER JOIN VehicleType ON vr.VehicleType = VehicleType.ID
LEFT OUTER JOIN (
SELECT ID, VehicleRegID, DateEffective, IVehHire, FixedCostPerYear, VehicleParts, MaintenancePerMile
FROM VehicleFixedCosts vfc
JOIN (
select VehicleRegID, max(DateEffective) as DateEffective
from VehicleFixedCosts
where DateEffective <= getdate()
group by VehicleRegID
) t ON vfc.VehicleRegID = t.VehicleRegID and vfc.DateEffective = t.DateEffective
) AS dt
ON dt.VehicleRegID = vr.ID
Subquery underneath dt might need some grouping but without schema (and maybe sample data) it's hard to say which column should be involved in that.