teradata get rid of hardcoded financial year date - teradata

the current query is something like
SELECT field1, field2
FROM sometable
WHERE finished_date >'30/06/2014' or finished_date is null
Would like to have the '30/06/2014' not hardcoded in the view, so we don't need to update this and other views every time new financial year comes around.

oh...got it
SELECT field1, field2
FROM sometable
WHERE finished_date>'30/06/' || TRIM((EXTRACT (YEAR FROM ADD_MONTHS((ADD_MONTHS(date, 7)), -1)))-1 ) (date, format 'DD/MM/YYYY'))
OR (finished_date is null))

Related

Teradata macro with volatile table and CTE to insert data into a table

I need to create a teradata macro to extract information into a volatile table first, then do CTE to extract data from this volatile table and insert into a teradata table, tried different ways all fail, appreciate help!
CREATE MACRO database.macro_insertion_tablename AS (
CREATE VOLATILE TABLE vt AS
(
SELECT
id, bu,
CONCAT(TO_CHAR(comment_date, 'yyyy-mm-dd HH24:MI:SS'), ' ', action) AS full_action,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY date DESC) AS row_num,
COUNT(*) OVER (PARTITION BY id) as cnt
FROM database.table1
) WITH DATA UNIQUE PRIMARY INDEX(id, row_num) ON COMMIT PRESERVE ROWS;
WITH RECURSIVE cte (id, bu, act, rn) AS
(
SELECT
id, bu
,CAST(full_action AS VARCHAR(5000)) AS full_action
,row_num
FROM vt
WHERE row_num = cnt
UNION ALL
SELECT
vt.id, vt.bu
,cte.act || ' / ' || vt.full_action
,vt.row_num
FROM vt
JOIN cte On vt.id = cte.id AND vt.row_num = cte.rn - 1
)
INSERT INTO database.table (id, bu, full_action)
SELECT id, bu, act
FROM cte
WHERE rn = 1;
DROP TABLE vt;
);
DDL must be the only statement in a Teradata Macro.
As workaround you could switch to a Global Temporary Table which is defined once and then you simply Insert/Select into it instead of CREATE VOLATILE TABLE.
But in your case there's no need for a temp table plus inefficient recursive processing to get a "group concat":
SELECT id, max(bu) -- maybe min(bu)?
XmlAgg(Concat(To_Char(comment_date, 'yyyy-mm-dd HH24:MI:SS'), ' ', action)
ORDER BY comment_date) (VARCHAR(5000)) AS full_action
FROM database.table1
GROUP BY 1
will give you a similar result.
To follow up on my comments, you should be able to define multiple CTEs in the same statement. It may be tricky getting the RECURSIVE CTE to work, but it sounds like it's possible. Maybe something like this:
CREATE MACRO database.macro_insertion_tablename AS (
WITH vt (id, bu, full_action, row_num, cnt) AS
(
SELECT
id, bu,
CONCAT(TO_CHAR(comment_date, 'yyyy-mm-dd HH24:MI:SS'), ' ', action) AS full_action,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY date DESC) AS row_num,
COUNT(*) OVER (PARTITION BY id) as cnt
FROM database.table1
),
RECURSIVE cte (id, bu, act, rn) AS
(
SELECT
id, bu
,CAST(full_action AS VARCHAR(5000)) AS full_action
,row_num
FROM vt
WHERE row_num = cnt
UNION ALL
SELECT
vt.id, vt.bu
,cte.act || ' / ' || vt.full_action
,vt.row_num
FROM vt
JOIN cte On vt.id = cte.id AND vt.row_num = cte.rn - 1
)
INSERT INTO database.table (id, bu, full_action)
SELECT id, bu, act
FROM cte
WHERE rn = 1;
);
I don't have a Teradata system to test with, so not 100% it will work as-is, but give it a try. You may need to change RECURSIVE to WITH RECURSIVE and also the ordering of the CTE queries (i.e. put the RECURSIVE one first). Take a look at these two links:
Teradata Forum - Multiple With Clause
teradata Forum - Common Table Expressions

Return 0 if the date for a certain day does not have values

I'm doing a query to return the number of count records for a certain date.
The problem is when I use the GroupBy by a certain day, If the date have no records then the date for that day will not be shown in the output.
How can I achieve that?
I'm doing something like:
SELECT COUNT(History.Id)
FROM History
INNER JOIN User ON User.Id = History.UserId
WHERE (#StartDate = #NullDate OR History.CreatedOnDate >= #StartDate)
AND (#EndDate = #NullDate OR History.CreatedOnDate <= #EndDate)
GROUP BY History.CreatedOnDat
Example
01-08, 3 records
02-08, 2 records
04-08, 5 records
I need to have 03-08 with 0 records.
Create a temp table with one day per row:
Declare #StartDate datetime = '2016-08-01'
Declare #EndDate datetime = '2016-08-31'
declare #temp table
(
oneday datetime
);
WHILE #StartDate <= #EndDate
begin
INSERT INTO #temp VALUES (#StartDate);
SET #StartDate = Dateadd(Day,1, #StartDate);
end
select * from #temp
Then, simply join your query with this temp table.

Select weekend or weekday data from a table based on date param

How can I select data from a table based on weekday or weekend, like
if date is a weekday then select only historical weekday data from the table &
if date is a weekend then select only historical weekend data.
I have tried to do that in this way but no luck
DECLARE #MyDate DATE = '08/17/2013'
SELECT datename(dw,#MyDate)
SELECT * FROM MyTable
WHERE
datename(dw,DateColumnInTable) IN (
CASE WHEN (datename(dw,#MyDate) IN ('Saturday','Sunday')) THEN '''Saturday'',''Sunday'''
ELSE 'Monday'',''Tuesday'',''Wednesday'',''Thursday'',''Friday'
END )
Any I can see lots of data in my table for saturday and sunday but this query is giving me blank record set.
Here's one way:
DECLARE #MyDate DATE = '08/17/2013'
IF (DATEPART(weekday, #MyDate) IN (1,7))
SELECT *
FROM MyTable
WHERE DATEPART(weekday, DateColumnInTable) IN (1,7)
ELSE
SELECT *
FROM MyTable
WHERE DATEPART(weekday, DateColumnInTable) BETWEEN 2 AND 6
If you would like to do it in one clause you can do something like the following, but it may perform worse:
SELECT *
FROM MyTable
WHERE (DATEPART(weekday, #MyDate) IN (1,7) AND DATEPART(weekday, DateColumnInTable) IN (1,7))
OR (DATEPART(weekday, #MyDate) BETWEEN 2 AND 6 AND DATEPART(weekday, DateColumnInTable) BETWEEN 2 AND 6)

How to optimize SQLite indexes for query

I have a SQLite table as
CREATE TABLE T(
CategoryCode NVARCHAR(64) NOT NULL,
DateTime DateTime NOT NULL,
ItemCode NVARCHAR(64) NOT NULL,
ItemName NVARCHAR(64) NOT NULL,
ItemValue NUMERIC(28, 4) NOT NULL
)
The question is how to optimize indexes for the following query:
SELECT
CategoryCode
,ItemCode
,ItemName
,SUM(ItemValue) as TotalValue
FROM T
WHERE CategoryCode = 'Code1'
AND DateTime < '2012-01-04 00:00:00'
GROUP BY ItemCode
Thank you!
For the exact query, you will need an index on T(CategoryCode, DateTime) or T(DateTime, CategoryCode), depending on which column is more selective than the other.
However, it is unwise to create an index for a single query without a more holistic view on all access to the table.
e.g. You may find, for example, that if most data in the table has CategoryCode = 'Code1' then the index should only be created on the DateTime column.

how to update database field every year

I have a database which contains 2 fields called DateOfBirth and Age, for storing users DOB and age respectively. I want the Age column to be automatically incremented by 1 every year, according to the DOB matching server date.
What could be the best way for achieving this? I am using asp.net and sql server 2008.
Rather than store both the DateOfBirth and Age, create a computed column on the table that calculates the age:
[Age] AS datediff(year, DateOfBirth, getdate())
So in yout table creation:
-- Create Table with computed column
CREATE TABLE [dbo].[CCtest]
(
[id] [int] not NULL,
[DateOfBirth] [datetime] NULL,
-- etc...
[Age] AS datediff(year, DateOfBirth, getdate())
)
GO
If you want to persist the computed value add the PERSISTED keyword.
One possibility, if you want Age displayed in years and months:
[AgeInDays] AS datediff(day, DateOfBirth, getdate())
then create a view over your table that formats AgeInDays into years and months.
Here is another possibility, using a computed column of [AgeYears]:
create view vwCCtestAge
AS
select
id,
dateofbirth,
cast([AgeYears] as varchar(4)) + ' years ' +
cast(datediff(month, DateOfBirth, getdate())
- case when (AgeYears > 0) then (AgeYears - 1)*12
else 0
end as varchar(4)) + ' months' as Age
from cctest2
GO
[You should check for boundary cases...]

Resources