Teradata sql query - compare current day value with previous day value - teradata

I have 3 columns(CustomerId, Amount, ProcessDate) in a table (Customer).
Values are inserted daily in this table.
I want to get all the rows whose current day Amount is greater than previous day Amount.
CustomerId Amount Process_date
1 20 12/05/2021
2 30 12/05/2021
1 40 13/05/2021
2 25 13/05/2022
We have to print (1 40 13/05/2021) as 20 (previous day amount) is smaller than 40 (next day amount).
Query which I tried :-
select b.customerId, b.amount, b.process_date from customer a
join (select customerId, amount, process_date from customer where process_date = current_date ) as b
on
a.customerId = b.customerId and
a.process_date = current_date - 1 and a.amount < b.amount

Related

Display hourly based data for 24 hour in SQL Server

I want to display the hourly based report for the last 24 hour. I have tried but the problem is that it will display count only where particular hour contains data.
But I want to display count for an hour and if count not found then display 0 over there.
select
datepart(hour, upload_date) as [hour], count(*)
from
tbl_stories
where
upload_date > getdate() - 1
group by
datepart(hour, upload_date)
Output:
hour count
-------------
11 2
16 1
17 1
but I want to get a record in the following way.
hour count
-------------
1 0
2 0
3 5
.
.
.
.
24 1
You can use a value() clause to generate all the hours and then use left join:
select v.hh, count(s.upload_date)
from (values (0), (1), . . . (23)
) v(hh) left join
tbl_stories s
on datepart(hour, s.upload_date) = v.hh and
s.upload_date > getdate() - 1
group by v.hh
order by v.hh;
Note that hours go from 0 to 23.
If you don't want to list out the hours, a convenient generation method is a recursive CTE:
with hours as (
select 1 as hh
union all
select hh + 1
from hours
where hh < 23
)
select h.hh, count(s.upload_date)
from hours h
tbl_stories s
on datepart(hour, s.upload_date) = h.hh and
s.upload_date > getdate() - 1
group by h.hh
order by h.hh;

Retain values only for certain section of data in teradata

Below is the link of my previous quetsion.
Retain values till there is a change in value in Teradata
It worked as suggested by one of the community members #Dnoeth. Can this retention be done only for certain section of data?
I.e, Retain data only for data where Dep is A or B . When Dep is C just use same value as input and no need to retain till certain value.
Data:
Cust_id Balance st_ts Dep
123 1000 27MAY2018 A
123 350 31MAY2018 A
256 2000 29MAY2018 B
345 1000 28APR2018 C
345 1200 26MAY2018 C
Output reqd:
Cust_id Balance st_ts Dep
123 1000 27MAY2018 A
123 1000 28MAY2018 A
123 1000 29MAY2018 A
123 1000 30MAY2018 A
123 350 31MAY2018 A
256 2000 29MAY2018 B
256 2000 30MAY2018 B
256 2000 31MAY2018 B
345 1000 28APR2018 C
345 1200 26MAY2018 C
Query used:
Wth cte
{
SELECT customer_id, bal, st_ts,
-- return the next row's date
Coalesce(Min(st_ts)
Over (PARTITION BY customer_id
ORDER BY st_ts
ROWS BETWEEN 1 Following AND 1 Following)
,Date '2018-06-01') AS next_Txn_dt
FROM BAL_DET;
}
SELECT customer_id, bal
,Last(pd) -- last day of the period
FROM cTE
-- make a period of the current and next row's date
-- and return one row per day
EXPAND ON PERIOD(ST_TS, next_Txn_dt) AS pd;
Thanks
Sandy
You can add a CASE to check for Dep = 'C':
WITH cte AS
( SELECT customer_id, bal, st_ts, dep,
-- return the next row's date
CASE
WHEN dep = 'C'
THEN st_ts +1 -- simply increase date
ELSE
Coalesce(Min(st_ts)
Over (PARTITION BY customer_id
ORDER BY st_ts
ROWS BETWEEN 1 Following AND 1 Following)
,DATE '2018-06-01')
END AS next_Txn_dt
FROM BAL_DET
)
SELECT customer_id, bal
,Last(pd) -- last day of the period
,dep
FROM cTE
-- make a period of the current and next row's date
-- and return one row per day
EXPAND ON PERIOD(ST_TS, next_Txn_dt) AS pd

SQLite count(*) in while clause

I have a calendar table in which there are all the dates in the future and a workday field:
fld_date / fld_workday
2014-01-01 / 1
2014-01-02 / 1
2014-01-03 / 0
...
I want select a date which are n workday far from another date. I tried two ways, but i failed:
The 5th workday from 2014-11-07:
1.
SELECT n1.fld_date FROM calendar as n1 WHERE n1.fld_workday=1 AND
(select count(*) FROM calendar as n2 WHERE n2.fld_date>='2014-11-07' AND n2.fld_workday=1)=5
It gave back 0 row.
2.
SELECT fld_date FROM calendar WHERE fld_date>='2014-11-07' AND fld_workday=1 LIMIT 1 OFFSET 5
It's ok, but i would like to change the 5 days constant to a field, and it's cannot (it would be inside a bigger select statement):
SELECT fld_date FROM calendar WHERE fld_date>='2014-11-07' AND fld_workday=1 LIMIT 1 OFFSET fld_another_field
Any suggestion?
In the first query, the subquery does not refer to the row in n1.
You need a correlated subquery:
SELECT fld_Date
FROM Calendar AS n1
WHERE fld_WorkDay = 1
AND (SELECT COUNT(*)
FROM Calendar AS n2
WHERE fld_Date BETWEEN '2014-11-07' AND n1.fld_Date
AND fld_WorkDay = 1
) = 5
LIMIT 1
The subquery is extremly inefficient if there is no index on the fld_Date column.
You can avoid executing the subquery for every row in n1 by adding another condition with an estimate of the result date (assuming that there are between about four to five work days per week, and using a few extra days to be sure):
...
WHERE fldDate BETWEEN date('2014-11-07', (5 * 4/7 - 10) || ' days')
AND date('2014-11-07', (5 * 5/7 + 10) || ' days')
AND fldWorkDay = 1
AND (SELECT ...

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)

T-SQL - Determine number of specific days between 2 dates based on sales

The Problem: Given a day of the week (1, 2, 3, 4, 5, 6, 7), a starting date and an ending date, compute the number of times the given day of the week appears between the starting and ending dates not inclusive of a date for which there were no sales.
Context:
Table "Ticket" has the following structure and sample content:
i_ticket_id c_items_total dt_create_time dt_close_time
----------------------------------------------------------------------------
1 8.50 '10/1/2012 10:23:00' '10/1/2012 11:05:05'
2 10.50 '10/1/2012 11:00:00' '10/1/2012 11:45:05'
3 8.50 '10/2/2012 08:00:00' '10/2/2012 09:25:05'
4 8.50 '10/4/2012 08:00:00' '10/4/2012 09:25:05'
5 7.50 '10/5/2012 13:22:23' '10/5/2012 14:33:27'
.
.
233 6.75 '10/31/2012 23:20:00' '10/31/2012 23:55:39'
Details
There may or may not be any tickets for one or more days during a month. (i.e. the place was closed that/those day/s)
Days in which the business is closed are not regular. There is no predictable pattern.
Based on Get number of weekdays (Sundays, Mondays, Tuesdays) between two dates SQL,
I have derived a query which returns the number of times a given day of the week occurs between the start date and the end date:
DECLARE #dtStart DATETIME = '10/1/2013 04:00:00'
DECLARE #dtEnd DATETIME = '11/1/2013 03:59:00'
DECLARE #day_number INTEGER = 1
DECLARE #numdays INTEGER
SET #numdays = (SELECT 1 + DATEDIFF(wk, #dtStart, #dtEnd)-
CASE WHEN DATEPART(weekday, #dtStart) #day_number THEN 1 ELSE 0 END -
CASE WHEN DATEPART(weekday, #dtEnd) <= #day_number THEN 1 ELSE 0 END)
Now I just need to filter this so that any zero-dollar days are not included in the count. Any help you can provide to add this filter based on the contents of the tickets table is greatly appreciated!
If I understand correctly, you can use a calendar table to count the number of days where the day of week is n and between the start and end and is a date that has ticket sales, which I guess is when the date exists in tickets and has the sum(c_items_total) > 0
WITH cal AS
(
SELECT cast('2012-01-01' AS DATE) dt, datepart(weekday, '2012-01-01') dow
UNION ALL
SELECT dateadd(day, 1, dt), datepart(weekday, dateadd(day, 1, dt))
FROM cal
WHERE dt < getdate()
)
SELECT COUNT(1)
FROM cal
WHERE dow = 5
AND dt BETWEEN '2012-04-01' AND '2012-12-31'
AND EXISTS (
SELECT 1
FROM tickets
WHERE cast(dt_create_time AS DATE) = dt
GROUP BY cast(dt_create_time AS DATE)
HAVING sum(c_items_total) > 0
)
OPTION (MAXRECURSION 0)
SQLFiddle

Resources