Sql query to multiply two column value to third column - sql

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... )

Related

What can I do to update my query to avoid a Division by zero error?

I'm trying to update my query to pull a list of stores if it is marked as "third party" and integrated_images_via_api is set to "true".
When returning these results, I would like to use the divide function to pull averages but i keep running into a division by zero error.
Looks like something went wrong with your query.
net.snowflake.client.jdbc.SnowflakeSQLException: Division by zero
With
menu_data as (
SELECT DISTINCT
dht.date_stamp,
dm.BUSINESS_ID,
ps.provider_type,
dht.MENU_ID,
dht.ACTIVE_STORES_LINKED_TO_MENU,
dht.HAS_HEADER_IMAGE,
dht.HAS_LOGO_IMAGE,
dht.PHOTOS_TOTAL,
dht.NUM_ITEM_IDS,
dht.ITEMS_WITH_DESCRIPTIONS,
dht.PHOTOS_TOTAL*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_photos,
dht.NUM_ITEM_IDS*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_items,
dht.ITEMS_WITH_DESCRIPTIONS*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_desc,
dht.HAS_HEADER_IMAGE*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_headers,
dht.HAS_logo_IMAGE*dht.ACTIVE_STORES_LINKED_TO_MENU as sum_logos,
case when dht.has_header_image AND dht.has_logo_image AND dht.photos_total/dht.NUM_ITEM_IDS >=0.1 --NS, >10% Photos
then 1
else 0 end as NS_Sat
FROM
PRODDB.PUBLIC.DIMENSION_MENU_HEALTH_TRACKING dht
Left Join PRODDB.PUBLIC.DIMENSION_MENU dm ON dm.MENU_ID = dht.MENU_ID
LEFT JOIN DOORDASH_MERCHANT.PUBLIC.MAINDB_STORE_POINT_OF_SALE_INFO ps on ps.store_id=dm.store_id
LEFT JOIN PRODDB.STATIC.POS_PROVIDER_CLASSIFICATION pc on pc.PROVIDER_TYPE=ps.PROVIDER_TYPE
LEFT JOIN PRODDB.STATIC.MENU_DETAILS pm on pm.PROVIDER_ID=pc.PROVIDER_TYPE
WHERE
1 = 1
AND dht.DATE_STAMP = (SELECT max(date_stamp) from PRODDB.PUBLIC.DIMENSION_MENU_HEALTH_TRACKING)
AND dht.ACTIVE_MENU
AND dht.NUM_ITEM_IDS >0
AND --dm.BUSINESS_ID in ('1026','57396','859','1037567','400712','554309')
pc.DIRECT_OR_3PT= 'Third Party'
AND pm.INTEGRATED_IMAGES_VIA_API= 'TRUE'
)
--Main Query
SELECT
md.DATE_STAMP,
business_id,
sum(ACTIVE_STORES_LINKED_TO_MENU) as total_store_menus,
sum(case when md.NS_SAT = 1 then ACTIVE_STORES_LINKED_TO_MENU else NULL end) as NS_store_menus,
total_store_menus - NS_store_menus as ns_opp,
round(NS_Store_menus / total_store_menus, 4) as NS_Perc,
sum(sum_photos) as total_photos,
sum(sum_items) as total_items,
sum(sum_desc) as total_descriptions,
sum(sum_headers) as total_headers,
round(total_photos / total_items,4) as item_perc,
round(total_descriptions / total_items,4) as desc_perc,
total_items - total_photos as item_opp,
round(total_headers / total_store_menus,4) as perc_headers
from menu_data md
where ns_perc >= 0.95
group by 1,2
order by 1,2 DESC

SQL how to count reocrds from date

I would like it to create a NUMBER column where the records for each date will be counted. So, for example, how many NRBs are there in 2021-10. However, when I choose count it gets such a result, sum cannot be because these are not numbers but an identification number
Here is my result:
Here my code:
PROC SQL; <- FIRST QUERY
create table PolisyEnd as
select distinct
datepart(t1.data_danych) as DATA_DANYCH format yymmdd10.
,(t4.spr_NRB) as NRB
,datepart(t1.PRP_END_DATE) as PRP_END_DATE format yymmdd10.
,datepart(t1.PRP_END_DATE) as POLICY_VINTAGE format yymmd7.,
case
when datepart(t1.PRP_END_DATE) IS NOT NULL and datepart(t1.PRP_END_DATE) - &gv_date_dly. < 0 THEN 'WYGASLA'
when datepart(t1.PRP_END_DATE) IS NOT NULL and datepart(t1.PRP_END_DATE) - &gv_date_dly. >= 0 and datepart(t1.PRP_END_DATE) - &gv_date_dly. <=7 THEN 'UWAGA'
when datepart(t1.PRP_END_DATE) IS NOT NULL and datepart(t1.PRP_END_DATE) - &gv_date_dly. >= 30 THEN 'AKTYWNA'
when datepart(t1.PRP_END_DATE) IS NULL THEN 'BRAK INFORMACJI O POLISIE'
end as POLISA_INFORMACJA
from
cmz.WMDTZDP_BH t1
left join
(select distinct kontr_id,obj_oid from cmz.BH_D_ZAB_X_ALOK_&thismonth) t2
on t2.obj_oid = t1.obj_oid
left join
(select distinct data_danych, kontr_id, kre_nrb from dm.BH_WMDTKRE_&thismonth) t3
on t3.kontr_id = t2.kontr_id
left join
(select distinct spr_NRB, spr_STATUS from _mart.mart_kred) t4
on t4.spr_NRB = t3.kre_nrb
where datepart(t1.data_danych) between '5Aug2019'd and &gv_date_dly. and t1.Actual = "T"
and t4.spr_STATUS ="A"
; SECOND CAME FROM FIRST
create table PolisyEnd1 as
select distinct
DATE_
,(POLICY_VINTAGE)
,count(NRB) as NUMBER
,POLISA_INFORMACJA
from PolisyEnd
where INFORMATION ="U"
;
Quit;
EDIT 1 :
I got the result, but how to do so that for 2021-11 there is one result and summed up all records for this period
Rather than using a distinct here what you really want is a GROUP BY.
PROC SQL;
create table PolisyEnd1 as
select
DATE_
,(POLICY_VINTAGE)
,count(NRB) as NUMBER
,POLISA_INFORMACJA
from PolisyEnd
where INFORMATION ="U"
group by DATE_, (POLICY_VINTAGE), POLISA_INFORMACJA
;
Quit;
You can use group by
If you want to count just based on the DATE_ column here is an example
select DATE_, count(NRB) as NUMBER
from PolisyEnd
where INFORMATION ="U"
group by DATE_
Otherwise, you can add other columns also in the group by and select clause.
For Edit1:
For each month you can use this:
select POLICY_VINTAGE, SUM(NUMBER) as NUMBER
from Your_Table
group by POLICY_VINTAGE

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

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):

Teradata / Combine records with a UNION not working

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...