Minimum date per year with flag - sql

Hi I have following data in customer table.
CUST_ID DATE
ab13563590 6/1/2008
ab13563591 1/1/2008
ab13563592 2/1/2008
ab13563593 8/1/2010
ab13563594 7/1/2010
ab13563595 9/1/2008
ab13563596 4/1/2008
ab13563597 10/1/2008
ab13563598 3/1/2009
ab13563599 5/1/2009
I need a calculated flag for which minimum date for every year will be 'Y' and 'N' for rest of them. Expected data should look like
CUST_ID DATE FLAG
ab13563590 6/1/2008 N
ab13563591 1/1/2008 Y
ab13563592 2/1/2008 N
ab13563593 8/1/2010 N
ab13563594 7/1/2010 Y
ab13563595 9/1/2008 N
ab13563596 4/1/2008 N
ab13563597 10/1/2008 N
ab13563598 3/1/2009 Y
ab13563599 5/1/2009 N
What I did is, I took group by year with min(date) and loaded data into temp table and join back to actual table and wrote a case statement. But I guess it can be solved in a single select statement.
Thanks in advance

You can solve this using Window Functions:
SELECT cust_id,
date,
CASE WHEN date = min(date) OVER (PARTITION BY EXTRACT(YEAR FROM date) ORDER BY date) THEN 'Y' ELSE 'N' END AS Flag
FROM table;
That will compare the date of the current row to the minimum date for the year. If they are equal, then you get a 'Y'.

Try this:
select cust_id,date,
case
when date = (select min(date) as min_date from customer where to_char(cust.date,'yyyy') = to_char(date,'yyyy'))
then 'Y' else 'N' end as flag
from customer cust

Related

Period over period SQL script?

I have a dataset of 2 columns: 'Date' and 'Total Sales'. My dates are 01-01-2021, 02-01-2021... so on and so forth up until 12-01-2022. I basically want to add another row where I have a "previous month" column that gives me the total sales for the previous month in the same row as the current month (else null) -- e.g. say I have 2 rows in my date column 01-01-2021 and 02-01-2021 and total sales would be $10 and $20 respectively. How do can I create a column that would show the following:
Date |Sales | Previous Month Sales|
---------------------------------------------
01-01-2021 | $10 | null
02-01-2021 | $20 | $10
So on and so forth; this is my query:
CASE
WHEN `Date` > DATE_SUB(`Date`, INTERVAL 1 MONTH)
THEN `Monthly Sales`
ELSE 'null'
END
Thanks in advance
Well, Domo's back-end is running a MySQL back-engine (from what I recall the last time I touched Domo [2018])
I think this is just a SQL question, and I wonder if a simple windowing function would do the trick.
select Date,
Sales,
max (case when *month* = *this month -1* then Sales else null end) over (order by 1) as "Previous Month Sales"
from table
You just need to figure out how to break down the Date into the month based on whatever SQL dialect Domo uses nowadays.
Cheers
I think domo support MySQL-like language, so you could do something like this:
with cte as
(
select date,
date + interval 1 month as next_month,
sales
from sales
)
select a.date,
a.sales as current_sales,
b.sales as prior_month_sales
from sales a
left join cte b
on b.next_month = a.date
order by a.date
I do this by joining the table onto itself with a LEFT OUTER JOIN. The outer join allows you to keep the null value for previous month. You match the date such that 1 column is calculated to show the previous month (I do this with EOMONTH() to ensure I always get the previous month and account for the year, if say it is January).
IF OBJECT_ID('TEMPDB..#TEMP') IS NOT NULL
DROP TABLE #TEMP
CREATE TABLE #TEMP(
[Date] DATE
,[Sales] INT
)
INSERT INTO #TEMP([Date],[Sales])
VALUES ('2020-12-20',50)
,('2021-01-20',100)
,('2021-02-20',200)
,('2021-03-20',300)
,('2021-04-20',400)
,('2021-05-20',500)
SELECT #TEMP.[Date]
,#TEMP.Sales
,TEMPII.Date [PREV M]
,TEMPII.Sales [PREV M SALES]
FROM #TEMP
LEFT OUTER JOIN #TEMP TEMPII
ON YEAR(EOMONTH(#TEMP.[Date],-1))*100+MONTH(EOMONTH(#TEMP.[Date],-1)) = YEAR(TEMPII.[Date])*100+MONTH(TEMPII.[Date])
ORDER BY #TEMP.[Date]
Output:

SQL Trailing Date Count

I have a need to do a calculation based on trailing dates when a customer placed an order.
SQL Code to get the following table:
select Date,Cust, ProdID, OrderLog
from AUDIT AS A
where Date >= '2021-02-07'
and Cust = '477'
and Prod ID = 'X'
order by A.Date desc
Date
Cust
ProdID
OrderLog
2/18/2021
477
X
Null
2/17/2021
477
X
1
2/16/2021
477
X
1
2/15/2021
477
X
1
2/14/2021
477
X
Null
2/13/2021
477
X
Null
What I want to do is count the days from 1st OrderLog Date, 2/15/2021, to last OrderLog Date 2/17/2021. For an outcome of 3.
I tried to do this in a window function using lag/over/partition with no luck. I also tried searching for the solution with no luck.
There is a need to do this in one query containing multiple Cust,PRODID and Dates. The count need to be at Cust and ProdID level.
Thanks for any help!
I think you want:
select Cust, ProdID,
max(date) - max(case when OrderLog = 1 then date end) as diff
from AUDIT AS A
where Date >= '2021-02-07' and
Cust = '477' and Prod ID = 'X'
group by cust, prodid;
Note that date/time functions vary among databases, so your database might use something other than - to subtract two dates.

Comparing dates in same column based on a condition in SQL / Hive

I have a table with the below schema.
Each person_id can have multiple codes (A,B,C,D etc) associated with them. For each person_id with code 'A' compare the corresponding date to the date of all other codes the person may have and filter out the dates to within 6 months of the date of code 'A'
So take example of the first person_id 30038590555, I want to make sure the date of code B and C are within 6 months of the date of A. Since both are above the 6 month threshold, they should be filtered out.
person_id code Date
30038590555 B 5/16/2017
30038590555 C 1/9/2019
30038590555 A 1/25/2020
37057397055 A 3/21/2020
38438355555 A 1/25/2020
59385393355 C 7/22/2014
59385393355 A 2/22/2020
44384037555 A 12/21/2019
49384037555 A 3/21/2020
50573409355 D 4/5/2016
50573409355 A 4/6/2016
50573409355 F 4/7/2016
50573409355 G 3/2/2017
50573409355 B 3/7/2017
This is interpreting "within 6 months as being "within 6 months after". The solution can be adapted if it really means 6 months before or after.
If I understand correctly, you want to keep all "A"s and then all others that are within six months of an A. Use a conditional running max:
select t.*
from (select t.*,
max(case when code = 'A' then date end) over (partition by person_id order by date) as prev_a_date
from t
) t
where code = 'A' or prev_a_date > add_months(date, -6)

Assign a Y/N flag based last 12 month activity

I'm working with a list of hospital patients and would like to flag each patient account with a "Y" if they were seen in the hospital nine or more times over the past 12 months.
I've come up with this, which would work fine if the patient list were static and only included a 12 month period:
SELECT
ENC.HSP_ACCOUNT_ID,
ENC.PAT_MRN_ID,
ENC.ADT_ARRIVAL_DTTM,
case when count(distinct txn.hsp_account_id) over(partition by PAT.PAT_MRN_ID) >= 9 then 'Y' else 'N' end as familiar_face_yn
FROM CLARITY.F_ED_ENCOUNTERS ENC
WHERE ENC.SERVICE_DATE BETWEEN '1-JUL-17' AND '31-OCT-18'
But I'd like to query the prior two years worth of data but only use the 12 months prior to the arrival date (ENC.ADT_ARRIVAL_DTTM) in calculating the Y or N.
The problem I'm running in to with the above query is that it's going back and counting all visits by a particular patient between 7/1/17 and 10/31/18.
What I'd like is that if the arrival date for a record is 8/1/18, it should count all visits between 8/1/17 and 8/1/18, ignoring anything with an arrival date earlier than 8/1/17 or later than 8/1/18.
Is this sort of "rolling" calculation possible? Many thanks!
You can use a windowing clause:
SELECT ENC.HSP_ACCOUNT_ID, ENC.PAT_MRN_ID, ENC.ADT_ARRIVAL_DTTM,
(CASE WHEN COUNT(DISTINCT txn.hsp_account_id) OVER
(PARTITION BY PAT.PAT_MRN_ID
ORDER BY ENC.SERVICE_DATE
RANGE BETWEEN 365 PRECEDING AND CURRENT ROW
) >= 9
THEN 'Y' ELSE 'N'
END) as familiar_face_yn
FROM CLARITY.F_ED_ENCOUNTERS ENC
WHERE ENC.SERVICE_DATE BETWEEN DATE '2017-07-01' AND DATE '2018-10-31'
with cte as
(
SELECT
ENC.HSP_ACCOUNT_ID,
ENC.PAT_MRN_ID,
ENC.ADT_ARRIVAL_DTTM,
-- find the most recent visit
max(ENC.ADT_ARRIVAL_DTTM) over(partition by PAT.PAT_MRN_ID) as last_date
FROM CLARITY.F_ED_ENCOUNTERS ENC
WHERE ENC.SERVICE_DATE BETWEEN '1-JUL-17' AND '31-OCT-18'
)
select ...
-- count all rows with within a 12 month range before the most recent visit
case when count(distinct case when ADT_ARRIVAL_DTTM >= add_months(last_date, -12) then txn.hsp_account_id end)
over (partition by PAT.PAT_MRN_ID) >= 9
then 'Y'
else 'N'
end as familiar_face_yn
from cte
I don't know if you really need the DISTINCT count...

SQL Oracle - Using RowNum in Query

I have two tables, examples as follows.
table_1
days special_day
10/09/2013 Y
10/10/2013 N
10/11/2013 Y
10/12/2013 N
10/13/2013 N
10/14/2013 Y
table_2
id special_day_ind numdays order
123 Y 3 2
456 N 5 1
My query would have to select the difference between sysday and the correct date from table_1 based on the parameters in table_2. If special_day_ind is 'Y', then I need 3 (numdays) special_days back from sysdate. If 'N', the numdays is the answer. Results would be ORDER(ed) BY order asc(ending).
In the above tables example, the query would return back.
sysdate = 10/14/2013
id days
456 5
123 5 (10/14/2013 - 10/9/2013)
It seems like ROWNUM would do the trick, however with the differing 'ways' of counting, I'm not sure how to proceed.
Here's a way to do it.
You need to assign a row number to special days in table_1.
select days,
row_number() over (order by days desc) r
from table_1
where special_day = 'Y';
Using this as CTE, you can find the earlier special days and subtract it from the sysdate.
with x as(
select days,
row_number() over (order by days desc) r
from table_1
where special_day = 'Y'
)
select id,
case when special_day_ind = 'N'
then numdays
when special_day_ind = 'Y'
then trunc(sysdate) - (select days
from x
where r = numdays)
end days
from table_2
order by order_;
Demo.