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
Related
So I might be stuck at something very trivial but can't figure out how to make it work. I create a 2 blocks of code that work in SQL but I have some problems with the date variable declaration in Oracle SQL.
I had write access to the SQL database when I create these codes so I did a 'Insert Into' to create temp tables. I don't have write access anymore. So I am using CTEs for it.
The original code looks like this:
DECLARE #Startdate Datetime = '2021-Jun-01 00:00:00.000'
DECLARE #Enddate Datetime = '2021-Jun-30 00:00:00.000'
Insert into Temp1
select ...
from ...
WHILE Startdate <= Enddate
BEGIN
Insert into Temp2
select ...
from (Temp 1)
left join
select ...
set #startdate=dateadd(d,1,#startdate)
end;
With my new code, I have made the following adjustmnets:
VARIABLE Startdate Datetime = '2021-Jun-01 00:00:00.000'
VARIABLE Enddate Datetime = '2021-Jun-30 00:00:00.000'
EXEC :Startdate := '2021-Jun-30 00:00:00.000'
EXEC :Enddate := '2021-Jun-30 00:00:00.000'
WITH Temp1 as (
select ...
from ...),
/* Unsure about using WHILE with with 2 CTEs so removing them for now but will need to be added*/
WITH Temp2 as
select ...
from (Temp 1)
left join
select ...
set startdate = :startdate + 1
end)
select * from Temp2;
The 2 blocks of code work perfectly individually. I think my concern lies with one or all of the following:
Variable Declaration - I read a couple of stackoverflow posts and it seems like there is binding variable and substitution variable. Is there a different way to declare variables?
The WHILE Loop specially between 2 CTEs. Can we do a while loop as a CTE? (similar to this) create while loop with cte
How the date is incremented. Is this the proper way to increment dates in Oracle PL/SQL?
Any guidance would be helpful.
Also adding 2 blocks of codes for reference:
Details of Tables:
Transactions - Contains Transaction information. Execution Date is a timestamp of the transaction execution
Account - Contains Account Information with a unique Account_Key for every account
Code_Rel - Maps the transaction code to a transaction type
Group Rel - Maps the transaction type to a transaction group
/***Block 1 of Code***/
insert into Temp1
select
a.ACCOUNT_KEY
,a.SPG_CD
,t.EXECUTION_DATE
from Schema_Name.TRANSACTIONS t
inner join Schema_Name.ACCOUNT a on a.en_sk=t.ac_sk
inner join Schema_Name.Code_Rel tr on t.t_cd_s = tr.t_cd_s
inner join ( select * from Schema_Name.Group_Rel
where gtrt_cd in ('Type1','Type2')) tt on tr.trt_cd = tt.trt_cd
where t.EXECUTION_DATE >= #startdate and t.EXECUTION_DATE<=#EndDt
and tt.gtrt_cd in ('Type1','Type2')
group by a.ACCOUNT_KEY ,a.SPG_CD, t.EXECUTION_DATE;
/***WHILE LOOP***/
while #startdate <= #EndDt
BEGIN
/***INSERT AND BLOCK 2 OF CODE***/
insert into Temp2
select table1.account_key, table1.SPG_CD, #startdate, coalesce(table2.sum_tr1,0),coalesce(table3.sum_tr2,0),
case when coalesce(table3.sum_tr2,0)>0 THEN coalesce(table2.sum_tr1,0)/coalesce(table3.sum_tr2,0) ELSE 0 END,
case when coalesce(table3.sum_tr2,0)>0 THEN
CASE WHEN coalesce(table2.sum_tr1,0)/coalesce(table3.sum_tr2,0)>=0.9 and coalesce(table2.sum_tr1,0)/coalesce(table3.sum_tr2,0)<=1.10 and coalesce(table2.sum_tr1,0)>=1000 THEN 'Yes' else 'No' END
ELSE 'No' END
FROM ( SELECT * FROM Temp1 WHERE execution_date=#startdate) TABLE1 LEFT JOIN
(
select a.account_key,a.SPG_CD, SUM(t.AC_Amt) as sum_tr1
from Schema_Name.TRANSACTIONS t
inner join Schema_Name.ACCOUNT a on a.en_sk=t.ac_sk
inner join Schema_Name.Code_Rel tr on t.t_cd_s = tr.t_cd_s
inner join ( select * from Schema_Name.Group_Rel
where gtrt_cd in ('Type1')) tt on tr.trt_cd = tt.trt_cd
where t.EXECUTION_DATE <= #startdate
and t.EXECUTION_DATE >=dateadd(day,-6,#startdate)
and tt.gtrt_cd in ('Type1')
group by a.account_key, a.SPG_CD
) table2 ON table1.account_key=table2.account_key
LEFT JOIN
(
select a.account_key,a.SPG_CD, SUM(t.AC_Amt) as sum_tr2
from Schema_Name.TRANSACTIONS t
inner join Schema_Name.ACCOUNT a on a.en_sk=t.ac_sk
inner join Schema_Name.Code_Rel tr on t.t_cd_s = tr.t_cd_s
inner join ( select * from Schema_Name.Group_Rel
where gtrt_cd in ('Type2')) tt on tr.trt_cd = tt.trt_cd
where t.EXECUTION_DATE <= #startdate
and t.EXECUTION_DATE >=dateadd(day,-6,#startdate)
and tt.gtrt_cd in ('Type2')
group by a.account_key, a.SPG_CD ) table3 on table1.account_key=table3.account_key
where coalesce(table2.sum_tr1,0)>=1000
set #startdate=dateadd(d,1,#startdate)
end;
You do not need to use PL/SQL or a WHILE loop or to declare variables and can probably do it all in a single SQL query using subquery factoring clauses (and recursion) to generate a calendar of incrementing dates. Something like this made-up example:
INSERT INTO temp2 (col1, col2, col3)
WITH time_bounds(start_date, end_date) AS (
-- You can declare the bounds in the query.
SELECT DATE '2021-06-01',
DATE '2021-06-30'
FROM DUAL
),
calendar (dt, end_date) AS (
-- Recursive query to generate a row for each day.
SELECT start_date, end_date FROM time_bounds
UNION ALL
SELECT dt + INTERVAL '1' DAY, end_date
FROM calendar
WHERE dt + INTERVAL '1' DAY <= end_date
),
temp1 (a, b, c) AS (
-- Made-up query
SELECT a, b, c FROM some_table
),
temp2 (a, d, e) AS (
-- Another made-up query.
SELECT t1.a,
s2.d,
s2.e
FROM temp1 t1
LEFT OUTER JOIN some_other_table s2
ON (t1.b = s2.b)
)
-- Get the values to insert.
SELECT t2.a,
t2.d,
t2.e
FROM temp2 t2
INNER JOIN calendar c
ON (t2.e = c.dt)
WHERE a BETWEEN 3.14159 AND 42;
If you try doing it with multiple inserts in a PL/SQL loop then it will be much slower than a single statement.
I have following table structure: http://sqlfiddle.com/#!4/952e7/1
Now I am looking for a solution for the following problem:
Given an input data-time set (see below). And the SQL statement should return all of business IDs with a given business name, where every single date-times of the input set are either present in the ORDERS table or an additional function's statement is true (these both conditions are separately to be checked for each input date-time).
An example how the input date-time dataset looks like:
WITH DATES_TO_CHECK(DATETIME) AS(SELECT DATE '2021-01-03' FROM DUAL UNION ALL SELECT DATE '2020-04-08' FROM DUAL UNION ALL SELECT DATE '2020-05-07' FROM DUAL)
To be simple, the "additional function" should be a simple random number (if greather than 0.5 than true otherwise false, so the check is dbms_random.value > 0.5).
For one given date time it would look like:
SELECT BN.NAME, BD.ID
FROM BUSINESS_DATA BD, BUSINESS_NAME BN
WHERE BD.NAME_ID=BN.ID AND
BN.NAME='B1' AND
(TO_DATE('2021-01-03', 'YYYY-MM-DD') IN (SELECT OD.ORDERDATE FROM ORDERS OD WHERE OD.BUSINESS_ID=BD.ID)
OR dbms_random.value > 0.5)
ORDER BY BD.ID
Please help me, how this solution can be applied to the input date-time rowset above AND the specified name.
I don't any difference with the question you just deleted
This is the list of businesses named B1 and for which the number of order dates that match date input dates is equal to the number of input dates or dbms_random.value > 0.5
see SQL Fiddle
WITH DATES_TO_CHECK(DATETIME) AS(
SELECT DATE '2021-01-03' FROM DUAL
UNION ALL SELECT DATE '2020-04-08' fROM DUAL
UNION ALL SELECT DATE '2020-05-07' fROM DUAL
),
businesses_that_match as (
select
od.BUSINESS_ID, count(distinct OD.ORDERDATE)
from DATES_TO_CHECK dtc
left join ORDERS od on OD.ORDERDATE = dtc.datetime
group by od.BUSINESS_ID
having count(distinct OD.ORDERDATE) = (select count(distinct DATETIME) from DATES_TO_CHECK)
)
SELECT
BN.NAME, BD.ID
FROM BUSINESS_DATA BD
inner join BUSINESS_NAME BN on BD.NAME_ID=BN.ID
left join businesses_that_match btm on btm.BUSINESS_ID = bd.id
where bn.name = 'B1'
AND (btm.BUSINESS_ID is not null
OR dbms_random.value > 0.5
)
I have a query below:
SELECT AIDI.LOAN_NUM, AIDI.LOCATION_CODE, AIDI.ORD_NUM, AIDI.MTN, AIDI.LOAN_STATUS, COUNT(*)
FROM table1 AIDI
WHERE AIDI.LOAN_STATUS = 'A'
AND EXISTS (SELECT 1 FROM ORDERS AO
WHERE AO.ACE_ORD_NUM = AIDI.ORD_NUM
AND AO.ACE_ORD_COMPLETION_TIME >= TRUNC(SYSDATE -1)
AND AO.ACE_ORD_COMPLETION_TIME < TRUNC(SYSDATE))
GROUP BY AIDI.LOAN_NUM, AIDI.LOCATION_CODE, AIDI.ORD_NUM, AIDI.MTN, AIDI.LOAN_STATUS
HAVING COUNT(*) > 1;
I need to get the AO.ACE_ORD_COMPLETION_TIME this column into select clause so that i can see the date also in the result set.
I am sorry for this but my previous question was not properly framed, so creating another post.
My question is similar to following question:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:14582643282111
I need to write inner query which will give me a list of dates between two date ranges to outer query.
My inner query returns following 2 rows:
SELECT request.REQ_DATE, request.DUE_DATE FROM myTable where id = 100
REQ_DATE DUE_DATE
3/19/2013 3/21/2013
3/8/2013 3/8/2013
So I need inner query which will return following dates to outer query:
3/19/2013
3/20/2013
3/21/2013
3/8/2013
The answer in above post has start date and end date hard coded and in my case, it is coming from other table. So I am trying to write query like this which does not work:
Select * from outerTable where my_date in
(
select to_date(r.REQ_DATE) + rownum -1 from all_objects,
(
SELECT REQ_DATE, DUE_DATE
FROM myTable where id = 100
) r
where rownum <= to_date(r.DUE_DATE,'dd-mon-yyyy')-to_date(r.REQ_DATE,'dd-mon-yyyy')+1;
)
with
T_from_to as (
select
trunc(REQ_DATE) as d_from,
trunc(DUE_DATE) as d_to
FROM myTable
where id = 100
),
T_seq as (
select level-1 as delta
from dual
connect by level-1 <= (select max(d_to-d_from) from T_from_to)
)
select distinct d_from + delta
from T_from_to, T_seq
where d_from + delta <= d_to
order by 1
I have the following query
SELECT ProgramDate, [CountVal]= COUNT(ProgramDate)
FROM ProgramsTbl
WHERE (Type = 'Type1' AND ProgramDate = '10/18/11' )
GROUP BY ProgramDate
What happens is that if there is no record that matches the Type and ProgramDate, I do not get any records returned.
What I like to have outputted in the above is something like the following if there is no values returned. Notice how for the CountVal we have 0 even if there are no records returned that fit the match condition:
ProgramDate CountVal
10/18/11 0
This is a little more complicated than you would like however, it is very possible. You will first have to create a temporary table of dates. For example, the query below creates a range of dates from 2011-10-11 to 2011-10-20
CREATE TEMPORARY TABLE date_stamps AS
SELECT (date '2011-10-10' + new_number) AS date_stamp
FROM generate_series(1, 10) AS new_number;
Using this temporary table, you can select from it and left join your table ProgramsTbl. For example
SELECT date_stamp,COUNT(ProgramDate)
FROM date_stamps
LEFT JOIN ProgramsTbl ON ProgramsTbl.ProgramDate = date_stamps.date_stamp
WHERE Type = 'Type1'
GROUP BY ProgramDate;
Select ProgramDate, [CountVal]= SUM(occur)
from
(
SELECT ProgramDate, 1 occur
FROM ProgramsTbl
WHERE (Type = 'Type1' AND ProgramDate = '10/18/11' )
UNION
SELECT '10/18/11', 0
)
GROUP BY ProgramDate
Because each SELECT statement is really building a table of records you can use a SELECT query to build a table with both the program count and a default count of zero. This would require two SELECT queries (one to get the actual count, one to get the default count) and using a UNION to combine the two SELECT results into a single table.
From there you can SELECT from the UNIONed table to sum the CountVals (if the programDate occurs in the ProgramTable the CountVal will be
CountVal of the first query if it exists(>0) + CountVal of the second query (=0)).
This way even if there are no records for the desired programDate in ProgramTable you will get a record back indicating a count of 0.
This would look like:
SELECT ProgramDate, SUM(CountVal)
FROM
(SELECT ProgramDate, COUNT(*) AS CountVal
FROM ProgramsTbl
WHERE (Type = 'Type1' AND ProgramDate = '10/18/11' )
UNION
SELECT '10/18/11' AS ProgramDate, 0 AS CountVal) T1
Here's a solution that works on SQL Server; not sure about other db platforms:
DECLARE #Type VARCHAR(5) = 'Type1'
, #ProgramDate DATE = '10/18/2011'
SELECT pt.ProgramDate
, COUNT(pt2.ProgramDate)
FROM ( SELECT #ProgramDate AS ProgramDate
, #Type AS Type
) pt
LEFT JOIN ProgramsTbl pt2 ON pt.Type = pt2.Type
AND pt.ProgramDate = pt2.ProgramDate
GROUP BY pt.ProgramDate
Grunge but simple and efficient
SELECT '10/18/11' as 'Program Date', count(*) as 'count'
FROM ProgramsTbl
WHERE Type = 'Type1' AND ProgramDate = '10/18/11'
Try something along these lines. This will establish a row with a date of 10/18/11 that will definitely return. Then you left join to your actual data to get your desired count (which can now return 0 if there are no corresponding rows).
To do this for more than 1 date, you'd want to build a Date table that holds a list of all dates you want to query (so substitute the "select '10/18/11'" with "select Date from DateTbl").
SELECT ProgDt.ProgDate, [CountVal]= COUNT(ProgramsTbl.ProgramDate)
FROM (SELECT '10/18/11' as 'ProgDate') ProgDt
LEFT JOIN ProgramsTbl
ON ProgDt.ProgDate = ProgramsTbl.ProgramDate
WHERE (Type = 'Type1')
GROUP BY ProgDt.ProgDate
To create a date table that you can use for querying, do this (assumes SQL Server 2005+):
create table Dates (MyDate datetime)
go
insert into Dates
select top 100000 row_number() over (order by s1.name)
from master..spt_values s1, master..spt_values s2
go