How can I use in teradata recurcive query? - teradata

Have a below table,
customer ID, code, start_date, end_date
124343, DCW, 2015-07-06, 2016-08-03
235432, ABC, 2015-04-26, NULL
235432, ABC, 2015-04-26, 2015-06-20
3242342, ABC, 2015-08-02, 2015-07-28
2332434, DCW, 2015-02-09, 2015-06-23
2332434, DCW, 2015-06-23, NULL
What to use recurcive query to get output for unique code for each customerID,
1. when customer ID has more than 1 record in table with value in end_date and null in end_date then only records with null end_date.
2. when customer ID has more than 1 record with start_date, end_date and start_date equal to end_date for the first record then only record with null end_date or future date than today's date.
3. end_date more than today's date
Required Output
customer ID, code, start_date, end_date
124343, DCW, 2015-07-06, 2016-08-03
235432, ABC, 2015-04-26, null
3242342, ABC, 2015-08-02, 2015-07-28
2332434, DCW, 2015-06-23, null

Related

Expand months between start date and end date in teradata

Need Query to expand the months between the start date and end date.
Below is one example of data.
Result is the output I would like to see.
Any help is much appreciated.
Example columns:
ID start date, End date
300 08/20/2021 10/25/2021
Result:
ID, Dateexpand
300 08/2021
300 09/2021
300 10/2021
Using Teradata's EXPAND on syntax (documentation):
select
id,
start_date,
end_Date,
prd,
last(prd) as end_month, --this will return the last date in the period
to_char(last(prd),'YYYYMM')
from
<your table>
expand on period (start_date,end_date) as prd BY ANCHOR PERIOD MONTH_BEGIN
I left all the columns in there so you can see what the PERIOD returns.
EDIT:
Period will not work if the ending date is not greater than the starting date. If you have cases where this isn't true, you'll have to process those separately and union them together:
select
id,
to_char(last(prd),'YYYYMM')
from
<your table>
where end_date > start_date
expand on period (start_date,end_date) as prd BY ANCHOR PERIOD MONTH_BEGIN
union
select
id,
to_char(start_date, 'YYYYMM')
from
<your table>
where end_date = start_date
order by 1,2

MariaDB group by date order by date desc not working

I have a table like this:
date
2020-03-11 10:41:26
2020-03-11 17:51:15
2020-03-12 10:45:28
2020-03-12 17:41:28
I want the result:
datech date cnt
2020年3月12日 2020-03-12 17:41:28 2
2020年3月11日 2020-03-11 17:51:15 2
I have tried
Select *, count(*) as cnt from (
Select (DATE_FORMAT((date),'%Y年%c月%d日')) as datech, date
from tablea where 1=1
order by date desc
) as t
GROUP BY datech order by date desc
but the result date is asc
datech date cnt
2020年3月12日 2020-03-12 10:45:28 2
2020年3月11日 2020-03-11 10:41:26 2
How can I desc date?
Thanks.
Try this:
Select datech, max(date) as date, count(*) as cnt from (
Select (DATE_FORMAT((date),'%Y年%c月%d日')) as datech, date
from tablea where 1=1
) as t
GROUP BY datech order by date desc;

Expected something between the word 'Alias Name' and the 'ON' keyword

I am trying to run this query and getting the below error.
Can you please let me know why this might be failing?
Error:Syntax error: expected something between the word 'FWI14' and the 'ON' keyword.
SELECT Command Failed.
Query:
SELECT FISCAL_MONTH, FISCAL_YEAR,
CASE WHEN END_dATE IS NOT NULL THEN 'C' ELSE 'X' END CURR_INDICATOR,
BEGIN_DATE,
END_DATE
FROM corp.fiscal_month_info FMI12
LEFT OUTER JOIN (SELECT END_dATE FROM corp.fiscal_week_info
WHERE CURRENT_dATE BETWEEN BEGIN_dATE AND END_dATE) AS FWI14
ON FWI14.FISCAL_MONTH = FMI12.FISCAL_MONTH
AND FWI14.FISCAL_YEAR = FMI12.FISCAL_YEAR
Pls remove below bold command(AS). This is not a column you are aliasing but a subquery.
SELECT FISCAL_MONTH, FISCAL_YEAR,
CASE WHEN END_dATE IS NOT NULL THEN 'C' ELSE 'X' END CURR_INDICATOR,
BEGIN_DATE,
END_DATE
FROM corp.fiscal_month_info FMI12
LEFT OUTER JOIN (SELECT END_dATE FROM corp.fiscal_week_info
WHERE CURRENT_dATE BETWEEN BEGIN_dATE AND END_dATE) **AS** FWI14
ON FWI14.FISCAL_MONTH = FMI12.FISCAL_MONTH
AND FWI14.FISCAL_YEAR = FMI12.FISCAL_YEAR

Teradata ROWS UNBOUNDED PRECEDING

I have below data set with me. I want to ensure that for any particular ID start_date, end_date and the period in between these two dates are not overlapping with dates of any other ID.
ID Start_Date End_Date
101 01-01-2001 31-01-2001
102 01-02-2001 28-02-2001
103 26-02-2001 31-03-2016
104 15-03-2001 30-04-2001
105 01-05-2002 31-05-2002
106 05-12-2002 31-12-2002
107 15-12-2002 05-01-2003
To do this I created below query:
select id,start_date,end_date,
case
when
end_date < max(end_date) over(order by start_date rows unbounded preceding)
then 'overlapping'
when
start_date < max(end_date) over(order by start_date rows unbounded preceding)
then 'overlapping'
else 'non-overlapping'
end as FLAG from table
I am getting below output having all flag as 'overlapping' which is not correct. I think 'rows unbounded preceding' is taking current row also in calculation:
Can you please let me know where I am wrong:
ID Start_Date End_Date Flag
101 01-01-2001 31-01-2001 Overlapping
102 01-02-2001 28-02-2001 Overlapping
103 26-02-2001 31-03-2016 Overlapping
104 15-03-2001 30-04-2001 Overlapping
105 01-05-2002 31-05-2002 Overlapping
106 05-12-2002 31-12-2002 Overlapping
107 15-12-2002 05-01-2003 Overlapping
There are a couple of ways to go about this. Since date ranges overlapping can get tricky, I would use Teradata's Period logic and a self join:
SELECT
*
FROM
table t1
INNER JOIN table t2 ON
period(t1.start_date, next(t1.end_date)) P_INTERSECT period(t2.start_date, next(t2.end_date)) IS NOT NULL
That will convert your start and end dates to a PERIOD data type and then look for records that have intersecting periods. The results will be the two records, combined into a single record, where the overlap takes place.
You can also try it the old-fashioned way, like:
CREATE TABLE db.t
(id INT,
start_date DATE,
end_date DATE);
INSERT INTO db.t VALUES (101,'2001-01-01','2001-01-31');
INSERT INTO db.t VALUES (102,'2001-02-01','2001-02-28');
INSERT INTO db.t VALUES (103,'2001-02-26','2001-03-31');
INSERT INTO db.t VALUES (104,'2001-03-15','2001-04-30');
INSERT INTO db.t VALUES (105,'2002-05-01','2002-05-31');
INSERT INTO db.t VALUES (106,'2002-12-05','2002-12-31');
INSERT INTO db.t VALUES (107,'2002-12-01','2003-01-05');
SELECT
t.id,
t.start_date,
t.end_date,
MAX(CASE WHEN o.id IS NULL THEN 'non-overlapping'
ELSE 'overlaps with' || o.id END) AS flag
FROM
db.t t LEFT OUTER JOIN
db.t o ON
t.start_date < o.end_date AND
t.end_date >= o.start_date AND
t.id <> o.id
GROUP BY 1,2,3
returns (sorted manually)
id start_date end_date flag
101 01/01/2001 01/31/2001 non-overlapping
102 02/01/2001 02/28/2001 overlaps with 103
103 02/26/2001 03/31/2001 overlaps with 104
104 03/15/2001 04/30/2001 overlaps with 103
105 05/01/2002 05/31/2002 non-overlapping
106 12/05/2002 12/31/2002 overlaps with 107
107 12/01/2002 01/05/2003 overlaps with 106

sqlite query comparing data in different rows

i have the following table where i have the date( not a primary key) and rating ('A' being the highest grade):
date rating
03-10-2010 C
03-09-2010 C
03-08-2010 B
03-07-2010 B
03-06-2010 B
03-05-2010 B
03-04-2010 A
I need to make a query where i compare the rating in order to return the result for each 'date'.
For example. considering the date 03-10-2010, i want to know when the last rating downgrade happened. if the downgrade was 1 day ago return '1' as result, if it was 2 days ago return '2' and if was older than 3 days return 0.
And i would do the same query for each date, getting an array with the results.
i'm stuck trying to do this and i have no more ideas how to do it. Anyone can help me please?
thanks.
You want the difference, in days, between the date of each record and the date of the record before the last downgrade.
When you have a specific record, the record before the last downgrade is the record that
has a higher rating than this record, and
has a lower date than this record, and
is the latest record of those.
In SQL, this can be done with a correlated subquery:
SELECT date,
rating,
(SELECT date
FROM MyTable AS downgrade
WHERE downgrade.date < MyTable.date
AND downgrade.rating < MyTable.rating
ORDER BY date DESC
LIMIT 1) AS downgrade_date
FROM MyTable
date rating downgrade_date
---------- ---------- ----------
2010-03-04 A
2010-03-05 B 2010-03-04
2010-03-06 B 2010-03-04
2010-03-07 B 2010-03-04
2010-03-08 B 2010-03-04
2010-03-09 C 2010-03-08
2010-03-10 C 2010-03-08
To compute the difference, convert the date into a numeric value.
You can then use this value for further computations:
SELECT date,
rating,
CASE
WHEN days <= 3 THEN days
ELSE 0
END AS whatever
FROM (SELECT date,
rating,
julianday(date) -
julianday((SELECT date
FROM MyTable AS downgrade
WHERE downgrade.date < MyTable.date
AND downgrade.rating < MyTable.rating
ORDER BY date DESC
LIMIT 1)) AS days
FROM MyTable)

Resources