Need to get the column from the table in exists clause - sql

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.

Related

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

Subquery resultset

I have a query below. Is this the right way to do a subquery?
SELECT App.State_Pstl_Name,
COUNT (DISTINCT App.APLCTN_ID) AS Total_APLCTN
FROM (Select count(distinct b.APLCTN_ID ),
A.Aplctn_Sk,
b.APLCTN_ID,
A.Lctn_Sk,
b.APLCTN_CREATD_DT,
B.Aplctn_Sbmtd_Dt,
c.STATE_PSTL_CD,
c.STATE_PSTL_NAME,
C.Urbn_Rrl_Ind
From MIDAS.Ee_Application_Mmbr_Fact A,
MIDAS.Insrnc_Aplctn_Dmnsn B,
Midas.Lctn_Dmnsn C
Where A.Lctn_Sk In (Select Lctn_Sk
From Midas.Lctn_Dmnsn
Where Flag_Actv_Rec = 'Y' ) And
A.Aplctn_Sk in (select Aplctn_Sk
from MIDAS.Insrnc_Aplctn_Dmnsn
Where Flag_Actv_Rec = 'Y' ) AND
(b.APLCTN_CREATD_DT >= '01-JUL-13' OR
b.APLCTN_CREATD_DT <= '01-JUL-31' )
GROUP BY A.Aplctn_Sk,
b.APLCTN_ID,
a.LCTN_SK,
b.APLCTN_CREATD_DT,
B.Aplctn_Sbmtd_Dt,
c.STATE_PSTL_CD,
c.STATE_PSTL_NAME,
c.URBN_RRL_IND) App
GROUP BY App.STATE_PSTL_NAME
Order By App.State_Pstl_Name

Query which gives list of dates between two date ranges

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

Select Statement Return 0 if Null

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

T-sql problem with running sum

I am trying to write T-sql script which will find "open" records for one table
Structure of data is following
Id (int PK) Ts (datetime) Art_id (int) Amount (float)
1 '2009-01-01' 1 1
2 '2009-01-05' 1 -1
3 '2009-01-10' 1 1
4 '2009-01-11' 1 -1
5 '2009-01-13' 1 1
6 '2009-01-14' 1 1
7 '2009-01-15' 2 1
8 '2009-01-17' 2 -1
9 '2009-01-18' 2 1
According to my needs I am trying to show only records after last sum for every one articles where 0 sorting by date of last running sum of zero value. So I am trying to abstract (show) records 5 and 6 for Art_id=1 and record 9 for art_id=2. I am using MSSQL2005 and my table has around 30K records with 6000 distinct values of ART_ID.
In this solution I simply want to find all the rows where there isn't a subsequent row for that Art_id where the running sum was 0. I am assuming we can use the ID as a better tiebreaker than TS, since two rows can come in with the same timestamp but they will get sequential identity values.
;WITH base AS
(
SELECT
ID, Art_id, TS, Amount,
RunningSum = Amount + COALESCE
(
(
SELECT SUM(Amount)
FROM dbo.foo
WHERE Art_id = f.Art_id
AND ID < f.ID
)
, 0
)
FROM dbo.[table name] AS f
)
SELECT ID, Art_id, TS, Amount
FROM base AS b1
WHERE NOT EXISTS
(
SELECT 1
FROM base AS b2
WHERE Art_id = b1.Art_id
AND ID >= b1.ID
AND RunningSum = 0
)
ORDER BY ID;
Complete working query:
SELECT
*
FROM TABLE_NAME E
JOIN
(SELECT
C.ART_ID,
MAX(TS) MAX_TS
FROM
(SELECT
ART_ID,
TS,
COALESCE((SELECT SUM(AMOUNT) FROM TABLE_NAME B WHERE (B.Art_id = A.Art_id) AND (B.Ts < A.Ts)),0) ROW_SUM
FROM TABLE_NAME A) C
WHERE C.ROW_SUM = 0
GROUP BY C.ART_ID) D
ON
(D.ART_ID = E.ART_ID) AND
(E.TS >= D.MAX_TS)
First we calculate running sums for every row:
SELECT
ART_ID,
TS,
COALESCE((SELECT SUM(AMOUNT) FROM TABLE_NAME B WHERE (B.Art_id = A.Art_id) AND (B.Ts < A.Ts)),0) ROW_SUM
FROM TABLE_NAME A
Then we look for last article with 0:
SELECT
C.ART_ID,
MAX(TS) MAX_TS
FROM
(SELECT
ART_ID,
TS,
COALESCE((SELECT SUM(AMOUNT) FROM TABLE_NAME B WHERE (B.Art_id = A.Art_id) AND (B.Ts < A.Ts)),0) ROW_SUM
FROM TABLE_NAME A) C
WHERE C.ROW_SUM = 0
GROUP BY C.ART_ID
You can find all rows where the running sum is zero with:
select cur.id, cur.art_id
from #articles cur
left join #articles prev
on prev.art_id = cur.art_id
and prev.id <= cur.id
group by cur.id, cur.art_id
having sum(prev.amount) = 0
Then you can query all rows that come after the rows with a zero running sum:
select a.*
from #articles a
left join (
select cur.id, cur.art_id, running = sum(prev.amount)
from #articles cur
left join #articles prev
on prev.art_id = cur.art_id
and prev.ts <= cur.ts
group by cur.id, cur.art_id
having sum(prev.amount) = 0
) later_zero_running on
a.art_id = later_zero_running.art_id
and a.id <= later_zero_running.id
where later_zero_running.id is null
The LEFT JOIN in combination with the WHERE says: there can not be a row after this row, where the running sum is zero.