Combining two SQL Queries and their results - sql

I am using Oracle database and I have written one SQL query using joins as below:
SELECT
(CT.CRDATTIM || CT.RECORDCD || CT.CRNODE) AS CALLERKEY
FROM
W67U999S F
JOIN
W03U999S CT
ON F.CCRDATTIM = CT.CRDATTIM
AND F.CRECORDCD = CT.RECORDCD
AND F.CCRNODE = CT.CRNODE
AND F.CRECORDCD = 'T'
AND CT.WRKTYPE = 'CALLER'
JOIN
PQCUSTSRV CDT
ON F.CCRDATTIM = CDT.CRDATTIM
AND F.CRECORDCD = CDT.RECORDCD
AND F.CCRNODE = CDT.CRNODE
WHERE
F.PCRDATTIM = '2019-01-29-06.10.33.037940'
AND F.PRECORDCD = 'F'
AND F.PCRNODE = '01'
AND CT.CRDATTIM < '9999-12-31-23.59.59.999999'
The above query returns me the following rows of data:
CALLERKEY
----------
2019-01-29-06.10.33.310940T01
2019-03-26-00.51.05.124040T01
2019-03-26-00.51.07.993040T01
2019-03-26-00.51.35.531040T01
2019-04-02-04.02.42.280040T01
Now I want to query for each row using the following SQL query to get some additional data that I am interested in:
Example as below:
SELECT COUNT(*) AS TESTCOUNT FROM PQCUSTSRV where CALLERKEY='2019-01-29-06.10.33.310940T01' AND TO_TIMESTAMP(CRDATTIM,'YYYY-MM-DD HH24.MI.SS.FF')
BETWEEN ADD_MONTHS(SYSTIMESTAMP,-12) AND SYSTIMESTAMP
The above query returns the following data:
TESTCOUNT
------------
2
Now I want to combine the above two queries and get the output as something like below:
CALLERKEY TESTCOUNT
---------- --------
2019-01-29-06.10.33.310940T01 2
2019-03-26-00.51.05.124040T01 3
2019-03-26-00.51.07.993040T01 2
2019-03-26-00.51.35.531040T01 1
2019-04-02-04.02.42.280040T01 4
How can I achieve that? Please let me know if you need any additional information.

with t as (
<first query here>
)
select t.callerkey, count(p.callerkey) AS TESTCOUNT
from t left join
PQCUSTSRV p
on p.callerkey = t.callerkey and
to_timestamp(p.CRDATTIM, 'YYYY-MM-DD HH24.MI.SS.FF') >= add_months(SYSTIMESTAMP, -12)
group by t.callerkey;
I changed the logic of the date comparison to just use >=, assuming that you don't have future values in crdattim.

You can use group by as follows:
Select F.CALLERKEY, COUNT(1) AS CNT
From (your_first_query) f
Left Join PQCUSTSRV s
On s.CALLERKEY=f.CALLERKEY AND TO_TIMESTAMP(CRDATTIM,'YYYY-MM-DD HH24.MI.SS.FF')
BETWEEN ADD_MONTHS(SYSTIMESTAMP,-12) AND SYSTIMESTAMP
Group by f.callerkey

Not tested but this should work
SELECT A.CALLERKEY, COUNT(*) AS TESTCOUNT
(SELECT (CT.CRDATTIM || CT.RECORDCD || CT.CRNODE) AS CALLERKEY
FROM W67U999S F
JOIN W03U999S CT
ON F.CCRDATTIM = CT.CRDATTIM
AND F.CRECORDCD = CT.RECORDCD
AND F.CCRNODE = CT.CRNODE
AND F.CRECORDCD = 'T'
AND CT.WRKTYPE = 'CALLER'
JOIN PQCUSTSRV CDT
ON F.CCRDATTIM = CDT.CRDATTIM
AND F.CRECORDCD = CDT.RECORDCD
AND F.CCRNODE = CDT.CRNODE
WHERE F.PCRDATTIM = '2019-01-29-06.10.33.037940'
AND F.PRECORDCD = 'F'
AND F.PCRNODE = '01'
AND CT.CRDATTIM < '9999-12-31-23.59.59.999999')A, PQCUSTSRV B
WHERE A.CALLERKEY=B.CALLERKEY AND TO_TIMESTAMP(CRDATTIM,'YYYY-MM-DD HH24.MI.SS.FF')
BETWEEN ADD_MONTHS(SYSTIMESTAMP,-12) AND SYSTIMESTAMP
GROUP BY B.CALLERKEY

Related

How can i optimize this oracle query?

i'm working with oracle 11g and we have a problem, well, this query takes forever to execute, the main table tbl_inc has about 17 million records, is there any way i can improve this query?
i can't add indexes, i don't have privileges for that.
SELECT count(*) FROM TBL_INC INC LEFT JOIN TBL_PDS P ON INC.SID = P.TRX
INNER JOIN TBL_ASTS ASTS ON ASTS.CODE = INC.CODE AND ASTS.MIT
= INC.MIT AND ASTS.OPE_PROD = 3
WHERE (INC.INC_DATE -1) >= to_date('29/10/20', 'DD/MM/YY')
AND INC.INC_DATE - 1 <= to_date('05/11/20', 'DD/MM/YY')
AND INC.OPE = 50 AND SUBSTR(INC.CARD_NMBR, 1, 6) = 123456
AND INC.MIT='05' AND INC.CODE='00';
thanks
First, I would rewrite this so the where clause does not have expressions on the columns:
SELECT count(*)
FROM TBL_INC INC LEFT JOIN
TBL_PDS P
ON INC.SID = P.TRX INNER JOIN
TBL_ASTS ASTS
ON ASTS.CODE = INC.CODE AND
ASTS.MIT = INC.MIT AND
ASTS.OPE_PROD = 3
WHERE INC.INC_DATE >= to_date('29/10/20', 'DD/MM/YY') + interval '1 day' AND
AND INC.INC_DATE - 1 <= to_date('05/11/20', 'DD/MM/YY') + interval '1 day' AND
INC.OPE = 50 AND
INC.CARD_NMBR LIKE '123456%' AND
INC.MIT = '05' AND INC.CODE = '00';
Then for this query, you want an index on: TBL_INC(MIT, CODE, OPE, INC_DATE, CARD_NMBR). I am guessing that you have indexes on the JOIN keys used in the other tables, but those would be TBL_PDS(TRX) and TBL_ASTS(CODE< MIT, OPE_PROD).
It is a very good practice to reduce the number of the rows from the join, rather that apply a 'where' condition to the end
SELECT count(1) FROM TBL_INC INC
INNER JOIN TBL_ASTS ASTS
ON ASTS.CODE = INC.CODE
AND ASTS.MIT = INC.MIT
AND ASTS.OPE_PROD = 3
AND INC.OPE = 50
AND SUBSTR(INC.CARD_NMBR, 1, 6) = 123456
AND INC.MIT='05'
AND INC.CODE='00'
AND (INC.INC_DATE -1) >= to_date('29/10/20', 'DD/MM/YY')
AND INC.INC_DATE - 1 <= to_date('05/11/20', 'DD/MM/YY')
LEFT JOIN
TBL_PDS P
ON INC.SID = P.TRX

Pl sql get x character of a string in a query

SELECT MR.MUSTERI_ROL_AD AS ACENTE_AD , ////HERE\\\\
(SELECT mrrt.musteri_rol_ad
FROM calisan ct, musteri_rol mrrt, musteri mmt
where ct.bagli_rol_id = a.acente_id
AND ct.calisan_rol_id = mrrt.musteri_rol_id
AND mrrt.musteri_id = mmt.musteri_id
AND ct.teknik_personel='H'
AND ct.calisan_rol_id is not null
and rownum < 2)Bayi_Yetkili_Kisi,
( case when M.TCK_NO is null then M.VKN_NO
else null end)VKN_NO,
(Select (SELECT taa.adresi
FROM tobb_acente ta, tobb_acente_adres taa
WHERE ta.levhano = a.levha_no
AND ta.tobb_acente_sorgu_id = taa.tobb_acente_sorgu_id
AND rownum < 2)
FROM musteri_adres mat, musteri_rol mrt, musteri mt, adres ad
WHERE mrt.musteri_rol_id = a.acente_id
AND mt.musteri_id = mrt.musteri_id
AND mat.musteri_id(+) = mt.musteri_id
AND ad.adres_id(+) = mat.adres_id AND rownum < 2) adress,
(SELECT mi.aciklama
FROM musteri_iletisim mi, musteri_rol_iletisim mri
where mi.musteri_id = m.musteri_id
AND mi.iletisim_tip_kod =
pck_const_iletisim_tip.cep_telefon()
AND mri.musteri_rol_id = mr.musteri_rol_id
and mi.musteri_iletisim_id = mri.musteri_iletisim_id
and rownum < 2) as CEpTELEFON ////// HERE \\\\\
FROM MUSTERI_ROL MR, MUSTERI M, ACENTE A,SATIS_KANALI SK
WHERE MR.MUSTERI_ID = M.MUSTERI_ID
AND MR.MUSTERI_ROL_ID = A.ACENTE_ID
AND A.SATIS_KANALI_ID = SK.SATIS_KANALI_ID
AND MR.ROL_ID = 1
AND A.Uretim_Kaynagi = 'E'
AND A.UST_ACENTE_ID is null
AND MR.Ust_Musteri_Rol_Id is null
AND M.VKN_NO != 'x'
AND TO_CHAR(TRUNC(MR.Bitis_Tarih), 'DD/MM/YYYY') is null or MR.Bitis_Tarih = SYSDATE
Hi guys i need some help about split in Oracle's SQL i get ACENTE_AD x character and i wanna see only first 5 character. and i get CEpTELEFON like 012345678 and i wanna split first 3 character(012) in a column and last 6 character(345678) the in other column. thanks.
You can use substr() string manipulation function to split your phone value in the outer select statement by considering your original query as a subquery.
SELECT t.Bayi_Yetkili_Kisi, t.Vkn_No, t.Adres,
substr(CepTelefonu,1,3) as AlanKodu, substr(CepTelefonu,-6) as CepTelefonu
FROM
(
SELECT MR.MUSTERI_ROL_AD AS ACENTE_AD,
(SELECT mrrt.musteri_rol_ad
FROM musteri_rol mrrt
JOIN calisan ct ON ct.calisan_rol_id = mrrt.musteri_rol_id
JOIN musteri mmt ON mmt.musteri_id = mrrt.musteri_id
WHERE ct.bagli_rol_id = a.acente_id
AND ct.teknik_personel = 'H'
AND ct.calisan_rol_id is not null
AND rownum < 2) as Bayi_Yetkili_Kisi,
(CASE
WHEN M.TCK_NO is null THEN
M.VKN_NO
ELSE
null
END) as Vkn_No,
(SELECT (SELECT taa.adresi
FROM tobb_acente ta
JOIN tobb_acente_adres taa
ON taa.tobb_acente_sorgu_id = ta.tobb_acente_sorgu_id
WHERE ta.levhano = a.levha_no
AND rownum < 2)
FROM musteri mt
JOIN musteri_rol mrt ON mrt.musteri_id = mt.musteri_id
LEFT JOIN musteri_adres mat ON mat.musteri_id = mt.musteri_id
LEFT JOIN adres ad ON ad.adres_id = mat.adres_id
WHERE mrt.musteri_rol_id = a.acente_id
AND rownum < 2) as Adres,
(SELECT mi.aciklama
FROM musteri_iletisim mi
JOIN musteri_rol_iletisim mri ON mri.musteri_iletisim_id = mi.musteri_iletisim_id
WHERE mi.musteri_id = m.musteri_id
AND mi.iletisim_tip_kod = pck_const_iletisim_tip.cep_telefon() -- I think the right hand side implies a stored function, doesn't it?
AND mri.musteri_rol_id = mr.musteri_rol_id
AND rownum < 2) as CepTelefonu
FROM MUSTERI_ROL MR
JOIN MUSTERI M ON M.MUSTERI_ID = MR.MUSTERI_ID
JOIN ACENTE A ON A.ACENTE_ID = MR.MUSTERI_ROL_ID
JOIN SATIS_KANALI SK ON SK.SATIS_KANALI_ID = A.SATIS_KANALI_ID
WHERE MR.ROL_ID = 1
AND A.Uretim_Kaynagi = 'E'
AND A.UST_ACENTE_ID is null
AND MR.Ust_Musteri_Rol_Id is null
AND M.VKN_NO != 'x'
AND to_char(trunc(MR.Bitis_Tarih), 'dd/mm/yyyy') is null
OR MR.Bitis_Tarih = sysdate
) t;
Btw, Consider using ANSI-92 style SQL rather than former ANSI-89 with comma-seperated tables written like the above one. It's easier to write, understand and maintain.

Get the sum of a count column in SQL

I have the following query
SELECT
dtc.coupon_type_company_name,
COUNT(*) * dtc.coupon_type_company_coupon_amount AS 'Total_Coupon_To_Be_Used',
dtc.coupon_type_company_coupon_months_combinable
FROM
[dbo].[coupon_type_Company_User] dtcu
JOIN
coupon_type_Company dtc ON dtcu.coupon_type_Company_ID = dtc.id
JOIN
person p ON dtcu.userID = p.userID
WHERE
coupon_type_company_coupon_is_combinable = 1
OR coupon_type_company_has_coupon = 1
AND dtc.companyID = 1081
AND p.is_active = 1
GROUP BY
dtc.coupon_type_company_name,dtc.coupon_type_company_coupon_amount,
dtc.coupon_type_company_coupon_months_combinable
This returns the following:
What I want to have however is just one column and one row that should take the SUM of my middle column (count(*)*dtc.coupon_type_company_coupon_amount).
How could I achieve this and prevent doing this in my code backend (C#)
You can wrap your query like this:
SELECT SUM(Total_Coupon_To_Be_Used) AS the_sum
FROM (
your query
) s
Use a "Table Expression", as in:
select sum(Total_Coupon_To_Be_Used) from (
SELECT dtc.coupon_type_company_name,
count(*) * dtc.coupon_type_company_coupon_amount as 'Total_Coupon_To_Be_Used',
dtc.coupon_type_company_coupon_months_combinable
FROM [dbo].[coupon_type_Company_User] dtcu
JOIN coupon_type_Company dtc ON dtcu.coupon_type_Company_ID = dtc.id
JOIN person p ON dtcu.userID = p.userID
WHERE coupon_type_company_coupon_is_combinable = 1
or coupon_type_company_has_coupon = 1
and dtc.companyID = 1081
AND p.is_active = 1
GROUP BY
dtc.coupon_type_company_name,dtc.coupon_type_company_coupon_amount,
dtc.coupon_type_company_coupon_months_combinable
) x

Update a join tables using SQL

This is my select query
select s.enabled,
s.totalpoints,
transaction_diff_dates
from loyalty_scheme l
join subscribe_merchant s on (l.scheme_id = s.schemerefid)
join transaction t on (s.unipoint_customer_ref_id = t.unipoint_customer_ref_id)
where (s.transaction_diff_dates = to_char(current_date, 'yyyy-MM-dd'))
and (s.merchant_ref_id = 11)
and (s.schemerefid = (select scheme_id
from loyalty_scheme
where (minimum_purchase_amount = (select min(minimum_purchase_amount)
from loyalty_scheme
where merchant_id = 11))
group by scheme_id))
group by s.unipoint_customer_ref_id,
s.enabled,
s.totalpoints,
s.transaction_diff_dates
This query returns two rows.
I need to update this enabled filed = 'false' , and totalPoint = 0 filed , instead of selecting
So I tried to write an update query
UPDATE subscribe_merchant
SET enabled = 'true'
FROM loyalty_scheme L
JOIN subscribe_merchant S ON (L.scheme_id = S.schemerefid)
JOIN transaction T ON (S.unipoint_customer_ref_id = T.unipoint_customer_ref_id)
WHERE (s.transaction_diff_dates = to_char(CURRENT_DATE, 'yyyy-MM-dd'))
AND (s.merchant_ref_id = 11)
AND (s.schemerefid = (SELECT scheme_id
FROM loyalty_scheme
WHERE (minimum_purchase_amount = (SELECT MIN(minimum_purchase_amount)
FROM loyalty_scheme
WHERE merchant_id = 11))
GROUP BY scheme_id))
GROUP BY
s.unipoint_customer_ref_id, s.enabled,
s.totalpoints, s.transaction_diff_dates
but this update query dose not work.
Please help me to write the update query

SQL Show dates without transactions as value = 0

I'm doing a weight reporting and I have a problem. I use this query to know the enters of weight in our warehouse, but when there are no transactions in a date this date doesn't appears in the results.
SELECT erp.MKPF.BUDAT AS Data,
Sum( erp.MSEG.MENGE * erp.MARM.BRGEW ) as pes
From erp.MKPF
INNER Join erp.MSEG on erp.MKPF.MANDT = erp.MSEG.MANDT and erp.MKPF.MBLNR = erp.MSEG.MBLNR
INNER Join erp.MARM on erp.MSEG.MANDT = erp.MARM.MANDT and erp.MSEG.MATNR = erp.MARM.MATNR And erp.MSEG.MEINS = erp.MARM.MEINH
INNER JOIN erp.MARA on erp.MSEG.MANDT = erp.MARA.MANDT and erp.MSEG.MATNR = erp.MARA.MATNR
WHERE erp.MKPF.MANDT = '100'
and erp.MKPF.BUDAT >= '20120720'
and erp.MKPF.BUDAT <= CONVERT(VARCHAR(8), GETDATE(), 112) -1
and erp.MSEG.LGORT in ('1001','1069')
and erp.MSEG.BWART In ('101','102','311','312')
and erp.MSEG.WERKS = '1001'
and erp.MARA.MTART in ('Z001','Z010','Z002','Z02E')
GROUP BY erp.MKPF.BUDAT*
Now the results are like this:
Data PES
20120720 9999999.9999
20120721 9999999.8888
20120723 9999999.7777
And i need this
Data PES
20120720 9999999.9999
20120721 9999999.8888
20120722 0
20120723 999999.7777
Can somebody help me?
Use a table or a view to generate the date range of interest and let this drive the query. Then you outer join your results to this view. This can be done dynamically in the query. For example, in Oracle, you can use "connect by" to generate a series:
create table my_summary(the_day date, pes number);
insert into my_summary values(to_date('20120720', 'yyyymmdd'), 9999999.9999);
insert into my_summary values(to_date('20120721', 'yyyymmdd'), 9999999.8888);
insert into my_summary values(to_date('20120723', 'yyyymmdd'), 9999999.7777);
SELECT d.the_day, NVL(s.pes, 0) AS pes
FROM ( SELECT to_date('20120720', 'yyyymmdd') + level -1 AS the_day
FROM dual CONNECT BY level <= 4) d
LEFT OUTER JOIN my_summary s ON (d.the_day = s.the_day)
ORDER BY 1
THE_DAY PES
--------- ---
20-JUL-12 9999999.9999
21-JUL-12 9999999.8888
22-JUL-12 0
23-JUL-12 9999999.7777
Other rdbms have other methods to generate a series. This will require you to know the start date you want, and the number of records (in the example above 20120720 and 4).
Thanks to all, finally I did this and it works
SELECT
c.BUDAT AS DATA,
CASE When SAP.pes Is Null then '0'
ELSE SAP.pes
END
From
erp.YSD_CALENDAR as c LEFT JOIN
(SELECT
erp.MKPF.BUDAT,
Sum(
erp.MSEG.MENGE
* erp.MARM.BRGEW ) as pes
FROM
erp.MKPF
INNER Join erp.MSEG on erp.MKPF.MANDT = erp.MSEG.MANDT and erp.MKPF.MBLNR = erp.MSEG.MBLNR
INNER Join erp.MARM on erp.MSEG.MANDT = erp.MARM.MANDT and erp.MSEG.MATNR = erp.MARM.MATNR And erp.MSEG.MEINS = erp.MARM.MEINH
INNER JOIN erp.MARA on erp.MSEG.MANDT = erp.MARA.MANDT and erp.MSEG.MATNR = erp.MARA.MATNR
WHERE
erp.MKPF.MANDT = '100'
and erp.MKPF.BUDAT >= '20120720'
and erp.MSEG.LGORT in ('1001','1069')
and erp.MSEG.BWART In ('101','102','311','312')
and erp.MSEG.WERKS = '1001'
and erp.MARA.MTART in ('Z001','Z010','Z002','Z02E')
and erp.MSEG.SHKZG = 'S'
GROUP BY erp.MKPF.BUDAT
) SAP ON SAP.BUDAT = c.BUDAT
WHERE
c.BUDAT >= '20120720'
and c.BUDAT <= CONVERT(VARCHAR(8), GETDATE(), 112)
GROUP BY c.BUDAT, SAP.pes
ORDER BY c.BUDAT