Teradata / Combine records with a UNION not working - sql

I have a query with a UNION. I was trying to combine 2 records into 1. The top half gets records from 1 set of tables and the bottom half gets records from a differen set of tables. Both halves use fields from 2 derived queries. The results currently look like this:
Group Branch Ref NUm GL Amt Bank Amt
135 15 1z2x3c 25.00 0.00
135 15 1z2x3c 0.00 25.00
What I would like to see is this:
135 15 1z2x3c 25.00 25.00
I added the fields with 0.00 in each half so I had the same number of columns since the 2 halves bring back different amount fields. I have also compared all of the fields and their datatypes. If they were different, then I used CAST to make them the same. Can I do this with a UNION or is there some other method to combines 2 rows into 1? I really appreciate your help. Thanks.........
This is the sql I have developed:
with drvd_qry (operating_unit, grp_brn_id, ecr_dept_id, stn_id) as
(select
soh.operating_unit,
s.grp_brn_id,
s.ecr_dept_id,
s.stn_id
from stns s
inner join rfs.stn_ops_hierarchies soh on soh.stn_stn_id = s.stn_id
where substr(s.grp_brn_id, 1, 2) = 'G1'
group by soh.operating_unit, s.grp_brn_id, s.ecr_dept_id, s.stn_id),
qry_drvd (department, ecr_ticket_no, open_item_id, rnt_agr_nbr, monetary_amount) as
(select
j.department,
j.ecr_ticket_no,
j.open_item_id,
j.rnt_agr_nbr,
cast(j.monetary_amount as decimal (15,2))
from
rfs.journal_entries j
where
j.business_unit = 'A0141'
and j.accounting_date = cast ('23-SEP-2015' as date format 'dd-MMM-YYYY')
and j.account_gl = '109850')
select
bb.BU,
bb.GPBR,
bb.STN_ID,
bb.DEPTID,
cast(ft.mrchnt_nbr as decimal (20,0)) as MERCH_NUM,
bb.TICKET_NUM,
ft.prim_acct_frst_six_dgt_nbr as FIRST6,
ft.prim_acct_last_four_dgt_nbr as LAST4,
bb.AUTH_NUM,
cast(ft.stlmt_uniq_ref_nbr as decimal (20,0)) as REF_NUM,
bb.GL_AMT,
bb.BANK_AMT
from
(select
aa.bu,
aa.gpbr,
aa.stn_id,
aa.deptid,
aa.ticket_num,
p.auth_nbr as AUTH_NUM,
p.fin_tran_ref_id,
aa.GL_AMT,
CAST(0 AS DECIMAL (15,2)) as BANK_AMT
from
(select
dq.operating_unit as BU,
dq.grp_brn_id as GPBR,
dq.stn_id as STN_ID,
qd.department as DEPTID,
qd.ecr_ticket_no as TICKET_NUM,
qd.open_item_id,
qd.rnt_agr_nbr,
cast(qd.monetary_amount as decimal (15,2)) as GL_AMT
from
qry_drvd qd,
drvd_qry dq
where dq.ecr_dept_id = qd.department ) aa
left outer join rfs.pymts p on p.ecr_pymt_id = cast(aa.open_item_id as decimal(19,0))
and p.ram_rea_rnt_agr_nbr = aa.rnt_agr_nbr) bb
left outer join paymt.fin_tran ft on ft.fin_tran_ref_id = bb.fin_tran_ref_id
UNION
select
b.BU,
b.GPBR,
b.STN_ID,
b.DEPTID,
cast(b.MERCH_NUM as decimal(20,0)),
qd.ecr_ticket_no as TICKET_NUM,
b.FIRST6,
b.LAST4,
b.AUTH_NUM,
cast(b.REF_NUM as decimal(20,0)),
b.GL_AMT,
b.BANK_AMT
from
(select
a.BU,
a.GPBR,
a.STN_ID,
a.DEPTID,
a.MERCH_NUM,
a.REF_NUM,
a.FIRST6,
a.LAST4,
p.auth_nbr as AUTH_NUM,
p.ecr_pymt_id,
a.GL_AMT,
a.BANK_AMT
from
(select
dq.operating_unit as BU,
dq.grp_brn_id as GPBR,
dq.stn_id as STN_ID,
dq.ecr_dept_id as DEPTID,
cast(f.merch_num as varchar(20)) as MERCH_NUM,
f.ret_ref_num as REF_NUM,
ft.prim_acct_frst_six_dgt_nbr as FIRST6,
ft.prim_acct_last_four_dgt_nbr as LAST4,
CAST(0 AS DECIMAL(15,2)) as GL_AMT,
cast(case when f.tran_typ_cde = 1 then f.tran_amt
when f.tran_typ_cde = 4 then f.tran_amt * -1
end as decimal (15,2)) as BANK_AMT,
ft.fin_tran_ref_id
from paymt.fndng_recncl_dtl_rprt f,
rfs.cc_mrchnt_nbr m,
drvd_qry dq,
paymt.fin_tran ft
--rfs.pymts p
where f.row_stat_cde = 'A'
and cast (f.tran_proc_date as date format 'MM/DD/YYYY') = '09/23/2015'
and m.mrchnt_nbr = f.merch_num
and m.credit_card_typ = 'VI'
and dq.stn_id = m.sta_stn_id
and ft.stlmt_uniq_ref_nbr = f.ret_ref_num
group by
dq.operating_unit,
dq.grp_brn_id,
dq.stn_id,
dq.ecr_dept_id ,
f.merch_num,
f.ret_ref_num,
ft.prim_acct_frst_six_dgt_nbr,
ft.prim_acct_last_four_dgt_nbr,
GL_AMT,
BANK_AMT,
ft.fin_tran_ref_id) a
left outer join rfs.pymts p on p.fin_tran_ref_id = a.fin_tran_ref_id) b
left outer join qry_drvd qd on cast(qd.open_item_id as decimal(19,0)) = b.ecr_pymt_id

Perform the union and then use group by and because you dummy fields are 0 use SUM to join both rows
SELECT "Group", "Branch", "Ref Num", SUM("GL Amt"), SUM("Bank Amt")
FROM (
SELECT * FROM YourQuery1
UNION ALL
SELECT * FROM YourQuery2
) as t
GROUP BY
"Group", "Branch", "Ref Num"

Since data is coming from two different tables and then I believe doing group by over the union will not help as derived table using with clause cannot be used inside subquery .If possible load this data to a a volatile table and then do group by and find the max of ("GL Amt"), ("Bank Amt") and or create a view and then query...

Related

SQL - Group values by range

I have following query:
SELECT
polutionmm2 AS metric,
sum(cnt) as value
FROM polutiondistributionstatistic as p inner join crates as c on p.crateid = c.id
WHERE
c.name = '154'
and to_timestamp(startts) >= '2021/01/20 00:00:00' group by polutionmm2
this query returns these values:
"metric","value"
50,580
100,8262
150,1548
200,6358
250,869
300,3780
350,505
400,2248
450,318
500,1674
550,312
600,7420
650,1304
700,2445
750,486
800,985
850,139
900,661
950,99
1000,550
I would need to edit the query in a way that it groups them toghether in ranges of 100, starting from 0. So everything that has a metric value between 0 and 99 should be one row, and the value the sum of the rows... like this:
"metric","value"
0,580
100,9810
200,7227
300,4285
400,2556
500,1986
600,8724
700,2931
800,1124
900,760
1000,550
The query will run over about 500.000 rows.. Can this be done via query? Is it efficient?
EDIT:
there can be up to 500 ranges, so an automatic way of grouping them would be great.
You can use generate_series() and a range type to generate the the ranges you want, e.g.:
select int4range(x.start, case when x.start = 1000 then null else x.start + 100 end, '[)') as range
from generate_series(0,1000,100) as x(start)
This generates the ranges [0,100), [100,200) and so on up until [1000,).
You can adjust the width and the number of ranges by using different parameters for generate_series() and adjusting the expression that evaluates the last range
This can be used in an outer join to aggregate the values per range:
with ranges as (
select int4range(x.start, case when x.start = 1000 then null else x.start + 100 end, '[)') as range
from generate_series(0,1000,100) as x(start)
)
select r.range as metric,
sum(t.value)
from ranges r
left join the_table t on r.range #> t.metric
group by range;
The expression r.range #> t.metric tests if the metric value falls into the (generated) range
Online example
You can create a Pseudo table with interval you like and join with that table.
I'll use recursive CTE for this case.
WITH RECURSIVE cte AS(
select 0 St, 99 Ed
UNION ALL
select St + 100, Ed + 100 from cte where St <= 1000
)
select cte.st as metric,sum(tb.value) as value from cte
inner join [tableName] tb --with OP query result
on tb.metric between cte.St and cte.Ed
group by cte.st
order by st
here is DB<>fiddle with some pseudo data.
use conditional aggregation
SELECT
case when polutionmm2>=0 and polutionmm2<100 then '100'
when polutionmm2>=100 and polutionmm2<200 then '200'
........
when polutionmm2>=900 and polutionmm2<1000 then '1000'
end AS metric,
sum(cnt) as value
FROM polutiondistributionstatistic as p inner join crates as c on p.crateid = c.id
WHERE
c.name = '154'
and to_timestamp(startts) >= '2021/01/20 00:00:00'
group by case when polutionmm2>=0 and polutionmm2<100 then '100'
when polutionmm2>=100 and polutionmm2<200 then '200'
........
when polutionmm2>=900 and polutionmm2<1000 then '1000'
end

Function to split value between columns in access

I have the following table:
And I need to split the value column into two columns based on the value of the status column, also add a difference between the two. Like This:
I was able to split it by using two separate queries, but when I merge them together I get duplicate values, even If I use the Sum and group by the costumer.
You can sue conditional aggregation:
select customer,
sum(iif(status = 'debt', value, 0)) as debt,
sum(iif(status = 'pay', value, 0)) as pay
(sum(iif(status = 'debt', value, 0)) -
sum(iif(status = 'pay', value, 0))
) as diff
from t
group by customer;
Try this please
tb1: Customer, value, status
select d.Customer, d.value as debt, IIf(p.value Is Null, 0, p.value) as pay, d.value - IIf(p.value Is Null, 0, p.value) as diff
from
(select Customer, value from tb1 where status = 'debt')d
left join
(select Customer, value from tb1 where status = 'pay')p on d.Customer = p.Customer
With a LEFT self join:
select t.Customer,
t.[value] as debt, tt.[value] as pay, t.[value] - Nz(tt.[value]) as diff
from tablename t left join tablename tt
on tt.customer = t.customer and t.[status] <> tt.[status]
where t.[status] = 'debt'
Results:
Customer debt pay diff
Fernando 445 445 0
Marcelo 332 123 209
Adriana 889 889

Use sql variables in query results

I have some of the following code:
Select p.CLIENT_NO,
s.CLIENT_NAME,
s.CLIENT_TYPE,
p.GL_CODE,
p.BATCH_KEY
From RU_POST p,
RU_ACCT a,
Ru_Ru s
Where
a.INTERNAL_KEY(+) = p.INTERNAL_KEY
And p.Batch_Key in
(Select Distinct (p1.BATCH_KEY)
From RU_POST p1
Where Abs(p1.AMOUNT) <> 0
And p1.POST_DATE Between To_Date('01-01-2015', 'dd-mm-yyyy') And
To_Date('01-01-2015', 'dd-mm-yyyy')
And p1.INTERNAL_KEY In ('367', '356'))
Now I want to have values stated in p1.INTERNAL_KEY to appear in query results, like if I did SELECT p1.INTERNAL_KEY.
However, I understand this won't work. So, it would be like '367' for 100 values, '356' for other 100.
Could someone help me how to put this condition value inside my result?
Like that:
CLIENT_NO CLIENT_SHORT CLIENT_NAME GL_CODE INTERNAL_KEY
399999000 399999 A 4568 367
599999000 599999 B 4879 356
You can try changing the in subquery to a join, like this:
select distinct
p.client_no
, s.client_name
, s.client_type
, p.gl_code
, p1.internal_key
from ru_post p
join ru_post p1 on p1.batch_key = p.batch_key
left join ru_acct a on a.internal_key = p.internal_key
cross join ru_ru s
where abs(p1.amount) <> 0
and p1.post_date between date '2015-01-01' and date '2015-01-01'
and p1.internal_key in ('367', '356') );
(Edited to match updated question - now left join ru_post to ru_acct):

Adding to sql query to join data from another table to current table

I have two sqls in microsoft query below which are in two seperate excel files, i'd like to make one main bit of sql in one excel file which combines both sql codes - so that the second sql (3 columns of data [z.ANALYSTNAME, z.MASTERCITYCODE, z.MEXID]) joins onto the first sql table based on the first column in each s.code and z.code being the same. Please see the 2 sqls below which return two tables:
`select
distinct
s.code as SEDOL, s.ISIN, s.Shortname as StockShortname, s.Fullname as
StockFullname, s.Status as StockStatus,
s.PriceKey as ExShareKey, s.IssueCcy as PriceCcy,
s.Catagory as Catagory,
decode(Catagory,'E','Equity','U','Unit Trust','G','Fixed Interest',
catagory) as CatagoryFull,
s.DealCCY as DealingCCY, s.IncomeCcy, s.EarningsCCY, s.noOfHolders,
s.Class as AssetClass, s.Depot as StockDepot,
s.StampScale as StampScale, s.REIT as REITFlag, s.LastBid,s.LastOffer,
S.PriceDate as LastPriceDate,
s.SecGroup as AssetGroup, ts.Fullname as AssetGroupDesc, ts.ShortName as
AssetGroupShort,
s.SecTypes as AssetType, tt.Fullname as AssetTypeDesc, tt.ShortName as
AssetTypeShort,
s.Indust as AssetSector, ti.Fullname as AssetSectorDesc,
s.Secmicropal as AssetSubSector, tm.Fullname as AseetSubSectorDesc,
s.SecCustom as AssetCustom, tsc.Fullname as AssetCustomDesc,
s.dealstyle as assetDealStyle,
ex.PriceFeed_code as exsharepricecode, ex.Country_Of_Incorporation as
exsharecoi
, round(nvl(h.Quantity,0),2) as TotalHoldingUnits
, round(nvl(h.Quantity,0)*((s.LastBid+s.LastOffer)/2 +
nvl(s.Accrued/100,0))/cs.LastBid,2) as HoldingsValueGBP
, sysdate as ValuesAsAtDate
, nvl(s.risk_rating,nvl(tm.type,ti.Type)) as RiskNumber,
case
when nvl(s.risk_rating,nvl(tm.type,ti.Type))=1 then 0
when nvl(s.risk_rating,nvl(tm.type,ti.Type))=2 then 0
when nvl(s.risk_rating,nvl(tm.type,ti.Type))=3 then 0
when nvl(s.risk_rating,nvl(tm.type,ti.Type))=4 then 0.5
when nvl(s.risk_rating,nvl(tm.type,ti.Type))=5 then 0.5
when nvl(s.risk_rating,nvl(tm.type,ti.Type))=6 then 0.5
when nvl(s.risk_rating,nvl(tm.type,ti.Type))=7 then 1
when nvl(s.risk_rating,nvl(tm.type,ti.Type))=8 then 1
when nvl(s.risk_rating,nvl(tm.type,ti.Type))=9 then 1
else null
end as EqRiskWeight,
s.Recommendation as StockRecommendation, s.recommenddate as
RecommendationDate,
s.ShareBenefits1 as Benefits1AlternateShareClass, s.ShareBenefits2 as
ResearchStyle,
s.ShareBenefits3 as PriceTarget, s.ShareBenefits4 as HouseModel,
FROM cpam.Security s,
cpam.TableSecGroup ts, cpam.TableSecTypes tt, cpam.TableIndust ti,
cpam.TableSecmpal tm, cpam.TableSecCustom tsc,
cpam.ExShare ex,
(SELECT h.Asset, sum(h.Quantity) as Quantity
FROM cpam.Holdings h
WHERE h.status='A' and h.Quantity<>0
GROUP BY h.Asset) h,
cpam.Currencies cs
WHERE s.Class = 'S' and s.code is not null
and S.SecGroup = ts.code(+)
and S.SecTypes = tt.code(+)
and S.Indust = ti.code(+)
and S.Secmicropal = tm.code(+)
and S.PriceKey = ex.code (+)
and s.SecCustom = tsc.code(+)
and s.code = h.asset(+)
and s.IssueCcy = cs.Code(+)
ORDER BY S.Shortname`
And second table:
'SELECT z.code, z.ANALYSTNAME, z.MASTERCITYCODE, z.MEXID
FROM CPAM_QRY.VIEW_CAM_STOCK_UNIV_STKDATA z'

Sql query to multiply two column value to third column

I want to multiply two columns value to 3rd column. Here is my query:
select distinct pr.PSProjectId,sfa.CodePattern, case when sfqd.NCR IS null then 'blank' else sfqd.NCR end as NCR
,
case when sfqd.NCR !='blank' then
(Select DATEDIFF(minute,starttime,EndTime) from ShopFloorStatusDetail where ShopFloorActivityId=sfa.ShopFloorActivityId
and StatusId=8
)
else
DATEDIFF(MINUTE,sfs.ShiftStarTime,sfs.shiftendtime)
end as timediff,
(select COUNT(1) from ShopFloorEmployeeTime where ShopFloorShiftId=sfs.ShopFloorShiftId) as totalemployee
from ShopFloor sf
inner join Project pr on pr.ProjectId=sf.ProjectId
inner join ShopFloorActivity sfa on sf.ShopFloorId=sfa.ShopFloorId
inner join ShopFloorShift sfs on sfs.ShopFloorActivityId=sfa.ShopFloorActivityId
left join ShopFloorStatusDetail sfsd on sfsd.ShopFloorActivityId=sfs.ShopFloorActivityId
left join ShopFloorQCDetail sfqd on sfqd.ShopFloorStatusDetailId=sfsd.ShopFloorStatusDetailId
and sfqd.NCR is not null
where CAST(sfs.ShiftStarTime as DATE) between '2014/01/06' and '2014/01/07'
and output from this query is
PSProjectId CodePattern NCR timediff totalemployee
0000129495 3TMEU blank 8 1
0000130583 3UA1P blank 1 1
0000130583 3UA1P blank 2090 2
Now i want to multiply column timediff and totalemployee and show it in a new column.
How do I do this? Please help.
Just add a new column, multiplying the existing expressions:
case when sfqd.NCR !='blank'
then (Select DATEDIFF(minute,starttime,EndTime)
from ShopFloorStatusDetail
where ShopFloorActivityId=sfa.ShopFloorActivityId
and StatusId=8
)
else DATEDIFF(MINUTE,sfs.ShiftStarTime,sfs.shiftendtime)
end
*
(select COUNT(1)
from ShopFloorEmployeeTime
where ShopFloorShiftId=sfs.ShopFloorShiftId)
Alternatively, wrap the whole existing query in another query, and multiply the calcualted columns:
select
PSProjectId,
CodePattern,
NCR,
timediff,
totalemployee,
timediff * totalemployee
from
( ...original query here... )