How can I get different data with case? - sql

In view If lokasyonno= 27 , I want the first block to run, if not the second block. How can I do it?
I tried to do it with the switch case structure, but I couldn't get a result because there is no common column.
FIRST
SELECT round(UH.NETTUTAR)
FROM TBL_IRSALIYE IR
INNER JOIN TBL_URUNHAREKETLERI UH ON UH.IRSALIYEID = IR.IRSALIYEID
INNER JOIN TBL_URUNLER U ON UH.URUNID = U.URUNID
WHERE IR.LOKASYONNO = 27
AND IR.TUR = 7
AND IR.IPTAL = 0
AND IR.ONAY = 1
AND IR.BILLED = 1
AND IR.INTERNET = 60
AND ROWNUM <= 10
AND IR.TARIH > TO_DATE ('2020-09-27 ', 'yyyy-mm-dd ')
AND IR.TARIH <= TO_DATE ('2020-10-05', 'yyyy-mm-dd ')
second
NVL (
(SELECT ROUND (
SUM (
CASE DOCUMENT_TYPE
WHEN 2
THEN
(CASE TRANSACTION_TYPE
WHEN 0
THEN
0
- ( LINE_TOTAL_VALUE
- LINE_TOTL_DISCOUNT)
ELSE
LINE_TOTAL_VALUE
- LINE_TOTL_DISCOUNT
END)
ELSE
(CASE TRANSACTION_TYPE
WHEN 1
THEN
0
- ( LINE_TOTAL_VALUE
- LINE_TOTL_DISCOUNT)
ELSE
( LINE_TOTAL_VALUE
- LINE_TOTL_DISCOUNT)
END)
END),
10)
FROM TBL_TRANSACTION_LINES
WHERE (TRANSACTION_TYPE NOT IN (10, 30))
AND STORE_NO = LOK.LOKASYONNO
AND (URUNID = TBL_URUNLER.URUNID)
AND TRANSACTION_DATE >
TO_DATE ('2020-09-27 0:0:0',
'yyyy-mm-dd HH24:MI:SS')
AND TRANSACTION_DATE <=
TO_DATE ('2020-10-04 0:0:0',
'yyyy-mm-dd HH24:MI:SS')),
0)
AS HAFTALIKKASASATISTUTARI

Use a union of the two queries but add a not exists() on the first query as an additional condition of the second query:
<first query>
union all
<second query>
where not exists (<first query>)

Related

Sql optimization query with join on Presto

I have the following query which shows out of all the clicks on products how many no of products have >1 image. The queries separately work fine but when combined its not able to execute within 3m threshold time. Any inputs how can this be optimized best.
select DATE (DATE_TRUNC('week',dt)) AS wk_dt,COUNT(DISTINCT a.product_id) tot_prods,COUNT(DISTINCT b.product_id) multiimp_prods,count(a.product_id) AS total_clicks,count(case when b.product_id>0 then a.product_id END) AS total_mulimg_clicks
from (
select product_id,DATE(from_unixtime((time/1000)+19800)) as dt--,count(distinct_id) clicks
from silver.mixpanel_android__product_clicked
WHERE DATE(from_unixtime((time/1000)+19800)) BETWEEN date(date_trunc('week',cast(Current_date - interval '14' day AS date))) AND Current_date
GROUP BY 1,2) a --2,471,245 1,458,476
LEFT join (
SELECT product_id,tot_img
FROM (SELECT DISTINCT product_id, catalog_id,(a + b + c + d + e) AS tot_img
FROM (
SELECT product_id,catalog_id,
CASE WHEN images is NULL then 0 else 1 end as a,
CASE WHEN img_2 is NULL then 0 else 1 end as b,
CASE WHEN img_3 is NULL then 0 else 1 end as c,
CASE WHEN img_4 is NULL then 0 else 1 end as d,
CASE WHEN img_5 is NULL then 0 else 1 end as e
FROM (
SELECT DISTINCT id AS product_id,catalog_id,
TRIM(images) AS images,
TRIM(SPLIT_PART(images,',',2)) AS "img_2",
TRIM(SPLIT_PART(images,',',3)) AS "img_3",
TRIM(SPLIT_PART(images,',',4)) AS "img_4",
TRIM(SPLIT_PART(images,',',5)) AS "img_5"
FROM silver.supply__products --WHERE date(created) <= date(date_trunc('week',cast(Current_date - interval '14' day AS date)))
)
--GROUP BY 1,2
order by 6 asc
)
)
WHERE tot_img>1
) b
on a.product_id=b.product_id
GROUP BY 1

Is there a way we can enhance the below query in Oracle 12C

Is there anyway we can optimize the below query in Oracle 12c to give faster result.
TAB_C - is the main table -2947109424 count and we have index in place on TAB_C(act_id).But still it is taking 3 hours to run in production.
SELECT ta.email_addr_id
, ta.email_addr
, SUBSTR(ta.email_addr, INSTR(ta.email_addr, '#') + 1,
INSTR(ta.email_addr, '.', -1) - INSTR(ta.email_addr, '#')
- 1) AS email_domain
, mtr.max_email_response_date
, ta.add_date
, net.num_12mons
, net.num_3mons
, net.num_6mons
, net.num_9mons
, ta.hard_bounce_ind
, ta.email_addr_text_att_02 AS preference_birth_date
,ta.source AS source
FROM Tab_A ta
LEFT JOIN (
SELECT tr.email_addr_id
, tcX(tr.email_response_date) AS max_email_response_date
FROM Tab_B tr
where tr.email_response_date = 'NEW'
AND tr.update_source <> 'EXP_EVENT'
GROUP BY tr.email_addr_id
) mtr
ON ta.email_addr_id = mtr.email_addr_id
LEFT JOIN (
SELECT tc.email_addr_id
, COUNT(DISTINCT tc.m_act_id) AS num_12mons
, COUNT(DISTINCT CASE WHEN ROUND(tc.outbound_date, 'DD')
> (ROUND(sysdate, 'DD') - 90)
THEN tc.m_act_id ELSE NULL END) AS num_3mons
, COUNT(DISTINCT CASE WHEN ROUND(tc.outbound_date, 'DD')
> (ROUND(sysdate, 'DD') - 180)
THEN tc.m_act_id ELSE NULL END) AS num_6mons
, COUNT(DISTINCT CASE WHEN ROUND(tc.outbound_date, 'DD')
> (ROUND(sysdate, 'DD') - 270)
THEN tc.m_act_id ELSE NULL END) AS num_9mons
FROM Tab_C tc
INNtr JOIN act a
ON tc.act_id = a.act_id
where a.channel_code IN ('FM','RM')
AND ROUND(tc.outbound_date, 'DD') > (ROUND(sysdate, 'DD') - 365)
GROUP BY tc.email_addr_id
) net
ON ta.email_addr_id = net.email_addr_id
where ta.email_addr_id <> 0 ;
Any insight will be highly appreciated.

how to add column value in postgresql?

My running query is
select
to_char(fs.order_item_id ,'99999999999')as Order_Item_Id ,
(case when (sum(fs.shipping_fee) < 0) then (-sum(fs.shipping_fee))else
sum(fs.shipping_fee) END) as Shipping_Fee_Charged ,
(case when (sum(se.shipping_fee) < 0) then (-sum(se.shipping_fee)) else
sum(se.shipping_fee) END) as Standard_Shipping_Charges ,
(case when (sum(fs.shipping_fee - se.shipping_fee) < 0) then (-
sum(fs.shipping_fee - se.shipping_fee)) else sum(fs.shipping_fee -
se.shipping_fee) END) as Error
from
"meta".fk_Payment as fs
join
"meta".ship_error as se
on
fs.order_item_id = se.order_item_id
where
(fs.order_status = 'delivered' and se.shipping_fee != 0 and(fs.shipping_fee-se.shipping_fee)< 0)
and
to_char(se.order_date, 'YYYY') = '2015'
and
to_char(se.order_date, 'Mon') = 'Feb'
group by
fs.order_item_id
limit 10;
as describe in above query calculate the column Shipping_Fee_Charged , Standard_Shipping_Charges , Error and show only 10 rows. Now i want to sum these column again, only 10 row .
How i can do this ?
You can use a subquery to store the result in a temporary table (T1 in the code below) and from that resultset find the sum
SELECT SUM(T1.Shipping_Fee_Charged), SUM(T1.Standard_Shipping_Charges), SUM(T1.Error)
FROM (
SELECT
to_char(fs.order_item_id ,'99999999999')as Order_Item_Id ,
(case when (sum(fs.shipping_fee) < 0) then (-sum(fs.shipping_fee))else
sum(fs.shipping_fee) END) as Shipping_Fee_Charged ,
(case when (sum(se.shipping_fee) < 0) then (-sum(se.shipping_fee)) else
sum(se.shipping_fee) END) as Standard_Shipping_Charges ,
(case when (sum(fs.shipping_fee - se.shipping_fee) < 0) then (-
sum(fs.shipping_fee - se.shipping_fee)) else sum(fs.shipping_fee -
se.shipping_fee) END) as Error
FROM "meta".fk_Payment as fs
JOIN "meta".ship_error as se ON fs.order_item_id = se.order_item_id
WHERE (fs.order_status = 'delivered' and se.shipping_fee != 0 and(fs.shipping_fee-se.shipping_fee)< 0) AND to_char(se.order_date, 'YYYY') = '2015' AND to_char(se.order_date, 'Mon') = 'Feb'
GROUP BY fs.order_item_id
LIMIT 10
) AS T1
You can also use WITH Queries (Common Table Expressions), which is similar to the above
WITH shipping_details AS (
SELECT
to_char(fs.order_item_id ,'99999999999')as Order_Item_Id ,
.
.
)
SELECT SUM(Shipping_Fee_Charged), SUM(Standard_Shipping_Charges), SUM(Error) FROM shipping_details

ORACLE SQL: Fill in missing dates

I have the following code which gives me production dates and production volumes for a thirty day period.
select
(case when trunc(so.revised_due_date) <= trunc(sysdate)
then trunc(sysdate) else trunc(so.revised_due_date) end) due_date,
(case
when (case when sp.pr_typ in ('VV','VD') then 'DVD' when sp.pr_typ in ('RD','CD')
then 'CD' end) = 'CD'
and (case when so.tec_criteria in ('PI','MC')
then 'XX' else so.tec_criteria end) = 'OF'
then sum(so.revised_qty_due)
end) CD_OF_VOLUME
from shop_order so
left join scm_prodtyp sp
on so.prodtyp = sp.prodtyp
where so.order_type = 'MD'
and so.plant = 'W'
and so.status_code between '4' and '8'
and trunc(so.revised_due_date) <= trunc(sysdate)+30
group by trunc(so.revised_due_date), so.tec_criteria, sp.pr_typ
order by trunc(so.revised_due_date)
The problem I have is where there is a date with no production planned, the date wont appear on the report. Is there a way of filling in the missing dates.
i.e. the current report shows the following ...
DUE_DATE CD_OF_VOLUME
14/04/2015 35,267.00
15/04/2015 71,744.00
16/04/2015 20,268.00
17/04/2015 35,156.00
18/04/2015 74,395.00
19/04/2015 3,636.00
21/04/2015 5,522.00
22/04/2015 15,502.00
04/05/2015 10,082.00
Note: missing dates (20/04/2015, 23/04/2015 to 03/05/2015)
Range is always for a thirty day period from sysdate.
How do you fill in the missing dates?
Do you need some kind of calendar table?
Thanks
You can get the 30-day period from SYSDATE as follows (I assume you want to include SYSDATE?):
WITH mydates AS (
SELECT TRUNC(SYSDATE) - 1 + LEVEL AS due_date FROM dual
CONNECT BY LEVEL <= 31
)
Then use the above to do a LEFT JOIN with your query (perhaps not a bad idea to put your query in a CTE as well):
WITH mydates AS (
SELECT TRUNC(SYSDATE) - 1 + LEVEL AS due_date FROM dual
CONNECT BY LEVEL <= 31
), myorders AS (
select
(case when trunc(so.revised_due_date) <= trunc(sysdate)
then trunc(sysdate) else trunc(so.revised_due_date) end) due_date,
(case
when (case when sp.pr_typ in ('VV','VD') then 'DVD' when sp.pr_typ in ('RD','CD')
then 'CD' end) = 'CD'
and (case when so.tec_criteria in ('PI','MC')
then 'XX' else so.tec_criteria end) = 'OF'
then sum(so.revised_qty_due)
end) CD_OF_VOLUME
from shop_order so
left join scm_prodtyp sp
on so.prodtyp = sp.prodtyp
where so.order_type = 'MD'
and so.plant = 'W'
and so.status_code between '4' and '8'
and trunc(so.revised_due_date) <= trunc(sysdate)+30
group by trunc(so.revised_due_date), so.tec_criteria, sp.pr_typ
order by trunc(so.revised_due_date)
)
SELECT mydates.due_date, myorders.cd_of_volume
FROM mydates LEFT JOIN myorders
ON mydates.due_date = myorders.due_date;
If you want to show a zero on "missing" dates instead of a NULL, use COALESCE(myorders.cd_of_volume, 0) AS cd_of_volume above.
what you can do is this :
creating a new table with all the days you need .
WITH DAYS AS
(SELECT TRUNC(SYSDATE) - ROWNUM DDD
FROM ALL_OBJECTS
WHERE ROWNUM < 365)
SELECT
DAYS.DDD
FROM
DAYS;
then full outer join between thoes table :
select DUE_DATE , CD_OF_VOLUME , DDD
from (
select
(case when trunc(so.revised_due_date) <= trunc(sysdate)
then trunc(sysdate) else trunc(so.revised_due_date) end) due_date,
(case
when (case when sp.pr_typ in ('VV','VD') then 'DVD' when sp.pr_typ in ('RD','CD')
then 'CD' end) = 'CD'
and (case when so.tec_criteria in ('PI','MC')
then 'XX' else so.tec_criteria end) = 'OF'
then sum(so.revised_qty_due)
end) CD_OF_VOLUME
from shop_order so
left join scm_prodtyp sp
on so.prodtyp = sp.prodtyp
where so.order_type = 'MD'
and so.plant = 'W'
and so.status_code between '4' and '8'
and trunc(so.revised_due_date) <= trunc(sysdate)+30
group by trunc(so.revised_due_date), so.tec_criteria, sp.pr_typ
order by trunc(so.revised_due_date)
) full outer join NEW_TABLE new on ( new .DDD = DUE_DATE )
where new .DDD between /* */ AND /* */ /* pick your own limit) */
you can get the gaps by using connect by and a left join:
assuming your schema is:
create table tbl(DUE_DATE date, CD_OF_VOLUME float);
insert into tbl values(to_date('14/04/2015','DD/MM/YYYY'),35267.00);
insert into tbl values(to_date('15/04/2015','DD/MM/YYYY'),71744.00);
insert into tbl values(to_date('16/04/2015','DD/MM/YYYY'),20268.00);
insert into tbl values(to_date('17/04/2015','DD/MM/YYYY'),35156.00);
insert into tbl values(to_date('18/04/2015','DD/MM/YYYY'),74395.00);
insert into tbl values(to_date('19/04/2015','DD/MM/YYYY'),3636.00);
insert into tbl values(to_date('21/04/2015','DD/MM/YYYY'),5522.00);
insert into tbl values(to_date('22/04/2015','DD/MM/YYYY'),15502.00);
insert into tbl values(to_date('04/05/2015','DD/MM/YYYY'),10082.00);
you can say:
with cte as
(
select (select min(DUE_DATE)-1 from tbl)+ level as dt
from dual
connect by level <= (select max(DUE_DATE)-min(DUE_DATE) from tbl)
)
select to_char(c.dt,'DD/MM/YYYY') gap,null volume
from cte c
left join tbl t on c.dt=t.DUE_DATE
where t.DUE_DATE is null
order by c.dt
Result:
GAP VOLUME
20/04/2015 (null)
23/04/2015 (null)
24/04/2015 (null)
25/04/2015 (null)
26/04/2015 (null)
27/04/2015 (null)
28/04/2015 (null)
29/04/2015 (null)
30/04/2015 (null)
01/05/2015 (null)
02/05/2015 (null)
03/05/2015 (null)
Notice: you can implement this in your original query, one simplest way is to wrap your query and use it as a subquery instead of tbl in above code snippet.

SQL Query group by

Pasted the sql query that is being used currently to generate the report from unix shell script. I want to have an addition column COUNT (cdw.file_id) writeoffcnt to the below sql query which displays the
count of the the record that matches mg_disp_status=0 and mig_disp_code =3 .
The existing field COUNT (cdw.file_id) cnt should have the count of record that matches
mg_disp_status = 1 and mig_disp_code <> 2. How can i modify the query?
SELECT fs.file_id,
fs.file_id_serv,
fs.file_process_dt,
fs.file_name,
fs.total_records,
RTRIM (d.description_text) source,
SUM(amount),
COUNT (cdw.file_id) cnt
FROM file_status fs,
dr_data_work cdw,
descriptions d,
contacts ec
WHERE file_process_dt >= TO_DATE ('${START_DATE}', 'DD-MON-YYYY')
AND file_process_dt < TO_DATE ('${END_DATE}', 'DD-MON-YYYY')
AND fs.ext_contact_id = ec.ext_contact_id
--
AND ec.description_code = d.description_code
AND cdw.file_id = fs.file_id
AND mg_disp_status = 1
AND mig_disp_code <> 2
GROUP BY fs.file_id,
fs.file_id_serv,
fs.file_process_dt,
fs.file_name,
fs.total_records,
RTRIM (d.description_text);
I don't fully understand all your permutations of requirements, but something like the following should work:
SELECT
.
.
.
SUM(CASE mg_disp_status=0 and mig_disp_code =3 THEN 1 ELSE 0 END) cnt1,
SUM(CASE mg_disp_status=1 and mig_disp_code <> 2 THEN 1 ELSE 0 END) cnt2,
Join twice with different aliases and do your counts:
SELECT fs.file_id,
fs.file_id_serv,
fs.file_process_dt,
fs.file_name,
fs.total_records,
RTRIM (d.description_text) source,
SUM(amount),
COUNT (cdw.file_id) cnt1, COUNT (cdw2.file_id) cnt2
FROM file_status fs,
dr_data_work cdw, dr_data_work cdw2,
descriptions d,
contacts ec
WHERE file_process_dt >= TO_DATE ('${START_DATE}', 'DD-MON-YYYY')
AND file_process_dt < TO_DATE ('${END_DATE}', 'DD-MON-YYYY')
AND fs.ext_contact_id = ec.ext_contact_id
--
AND ec.description_code = d.description_code
AND cdw.file_id = fs.file_id AND cdw2.file_id = fs.file_id
AND cdw.mg_disp_status = 1 AND cdw2.mg_disp_status = 0
AND cdw.mig_disp_code <> 2 AND cdw2.mg_disp_code = 3
GROUP BY fs.file_id,
fs.file_id_serv,
fs.file_process_dt,
fs.file_name,
fs.total_records,
RTRIM (d.description_text);