I have this table:
Original_Date Date_ Date_1 YearMonth YearMonth_1
03-07-2020 2020-07-03 2020-06-03 03-0 2020
13-03-2020 2020-03-13 2020-02-13 13-0 2020
08-01-2020 2020-01-08 2019-12-08 08-0 2019
13-11-2020 2020-11-13 2020-10-13 13-1 2020
23-03-2020 2020-03-23 2020-02-23 23-0 2020
30-07-2020 2020-07-30 2020-06-30 30-0 2020
13-07-2020 2020-07-13 2020-06-13 13-0 2020
24-01-2020 2020-01-24 2019-12-24 24-0 2019
05-10-2020 2020-10-05 2020-09-05 05-1 2020
11-07-2020 2020-07-11 2020-06-11 11-0 2020
Where if I use TYPE() function on them they return:
Original Date: VARCHAR
Date_: DATE
Date_1: DATE
YearMonth_1: VARCHAR
YearMonth: VARCHAR
These columns are built based on Original_Date column, where:
SELECT
Original_Date
CAST(Original_Date AS DATE FORMAT 'DD-MM-YYYY') AS Date_, -- This is in a subquery, put for simplicity I put it here
ADD_MONTHS(CAST(Original_Date AS DATE FORMAT 'DD-MM-YYYY'),-1) AS Date_1, -- This is in a subquery, put for simplicity I put it here
LEFT(CAST(Date_ AS varchar(10)),4) AS YearMonth,
LEFT(CAST(Date_1 AS varchar(10)),4) AS YearMonth_1,
FROM TABLE
The problem is:
I can't understand why YearMonth takes the last (right) four characters instead of the first (left) four characters.
I was looking for a YearMonth with type DATE and format like YYYY-MM. But as I didn't find any solution with Teradata (if you can provide one, it will be better than the workaround I'm doing now), I'm going for YYYYMM as integer, but as you can see when I'm applying LEFT() function it seem to work like a RIGHT() function, even when both (Date_ and Date_1) have the same data types. why? How can I solve this?
EDIT
SELECT
LEFT(CAST(Date_ AS varchar(10)),4) AS YearMonth_v2,
LEFT(CAST(Date_1 AS varchar(10)),4) AS YearMonth_1_v2,
FROM TABLE
Results in:
YearMonth_v2 YearMonth_1_v2
03-07-2020 2020-06-03
13-03-2020 2020-02-13
08-01-2020 2019-12-08
13-11-2020 2020-10-13
23-03-2020 2020-02-23
30-07-2020 2020-06-30
13-07-2020 2020-06-13
24-01-2020 2019-12-24
05-10-2020 2020-09-05
11-07-2020 2020-06-11
Why transforming the data type of these columns behave differently even when both of them (Date and Date_1) have the same data type and date format?
The big miss here is that you are fighting nature, or rather then nature of date storage and formatting in Teradata. If you run, as an example, the following:
SELECT
'03-07-2020' AS Original_Date,
CAST(Original_Date AS DATE FORMAT 'DD-MM-YYYY') AS Date_, -- This is in a subquery, put for simplicity I put it here
ADD_MONTHS(CAST(Original_Date AS DATE FORMAT 'DD-MM-YYYY'),-1) Date_1, -- This is in a subquery, put for simplicity I put it here
CAST(Date_ AS varchar(10)),
CAST(Date_1 AS varchar(10)),
LEFT(CAST(Date_ AS varchar(10)),4) AS YearMonth,
LEFT(CAST(Date_1 AS varchar(10)),4) AS YearMonth_1
+-----------------+------------+------------+--------------+--------------+-------------+---------------+
| "Original_Date" | "Date_" | "Date_1" | "Date_" | "Date_1" | "YearMonth" | "YearMonth_1" |
+-----------------+------------+------------+--------------+--------------+-------------+---------------+
| "03-07-2020" | 2020-07-03 | 2020-06-03 | "03-07-2020" | "2020-06-03" | "03-0" | "2020" |
+-----------------+------------+------------+--------------+--------------+-------------+---------------+
You'll notice that the return of the ADD_MONTHS() function is a date formatted in the Teradata default of YYYY-MM-DD. This is why your attempt to use the LEFT() string function against both of these dates is yielding strange results.
To correct you can just flip that first YearMonth to use the RIGHT() function instead of LEFT or you can re-cast the date format of your DATE_ like:
SELECT
'03-07-2020' AS Original_Date,
CAST(CAST(Original_Date AS DATE FORMAT 'DD-MM_YYYY') AS DATE FORMAT 'YYYY-MM-DD') AS Date_, -- This is in a subquery, put for simplicity I put it here
ADD_MONTHS(CAST(Original_Date AS DATE FORMAT 'DD-MM-YYYY'),-1) Date_1, -- This is in a subquery, put for simplicity I put it here
CAST(Date_ AS varchar(10)),
CAST(Date_1 AS varchar(10)),
LEFT(CAST(Date_ AS varchar(10)),4) AS YearMonth,
LEFT(CAST(Date_1 AS varchar(10)),4) AS YearMonth_1
+-----------------+------------+------------+--------------+--------------+-------------+---------------+
| "Original_Date" | "Date_" | "Date_1" | "Date_" | "Date_1" | "YearMonth" | "YearMonth_1" |
+-----------------+------------+------------+--------------+--------------+-------------+---------------+
| "03-07-2020" | 2020-07-03 | 2020-06-03 | "2020-07-03" | "2020-06-03" | "2020" | "2020" |
+-----------------+------------+------------+--------------+--------------+-------------+---------------+
The take-away here is that in Teradata if you want to change the format of the date, you MUST use a cast statement so sometimes you'll find yourself casting multiple times, plus Teradata has the tendency to gravitate to the default 'YYYY-MM-DD'. I've found it best to just go with the default so there are no surprises.
If you want to format a date/timestamp, the easiest way is TO_CHAR plus a format, e.g.
TO_CHAR(date_col, 'YYYY-MM') AS YearMonth
To get a YYYYMM integer:
Extract(YEAR From date_col) * 100
+ Extract(MONTH From date_col)
Simple rules:
FORMAT clauses are only applied when converting some other data type to character string or vice versa. (This could be an explicit CAST, or an implicit conversion triggered by applying a function that only operates on strings to a different data type.)
Applying a FORMAT to something does not change how the value is stored.
When retrieving a value with a data type other than character string, the client is responsible for any formatting performed; the database FORMAT clause will be ignored. (In other words, if you want the database to format the data, you need something in your SQL that forces conversion to character string.)
Related
I have a table which contains a column Start_Timestamp which has time stamp values like 2020-06-02 21:08:37. I would like to create new column which classifies these timestamps into bins of 6hours.
Eg.
Input :
Start_Timestamp
2020-06-02 21:08:37
2020-07-19 01:23:40
2021-11-13 12:08:37
Expected Output ( Here each bin is of 6hours width) :
Start_Timestamp
Bin
2020-06-02 21:08:37
18H - 24H
2020-07-19 01:23:40
00H - 06H
2021-11-13 12:08:37
12H - 18H
I have tried using TIMESERIES but can anyone help to generate output in following format
It's Vertica. Use the TIME_SLICE() function. Then, combine it with the TO_CHAR() function that Vertica shares with Oracle.
You can always add a CASE WHEN expression to change 00:00 to 24:00, but as that is not the standard, I wouldn't even bother.
WITH
indata(start_ts) AS (
SELECT TIMESTAMP '2020-06-02 21:08:37'
UNION ALL SELECT TIMESTAMP '2020-07-19 01:23:40'
UNION ALL SELECT TIMESTAMP '2021-11-13 12:08:37'
)
SELECT
TIME_SLICE(start_ts,6,'HOUR')
AS tm_slice
, TO_CHAR(TIME_SLICE(start_ts,6,'HOUR'),'HH24:MIH - ')
||TO_CHAR(TIME_SLICE(start_ts,6,'HOUR','END'),'HH24:MIH')
AS caption
, start_ts
FROM indata;
-- out tm_slice | caption | start_ts
-- out ---------------------+-----------------+---------------------
-- out 2020-06-02 18:00:00 | 18:00H - 00:00H | 2020-06-02 21:08:37
-- out 2020-07-19 00:00:00 | 00:00H - 06:00H | 2020-07-19 01:23:40
-- out 2021-11-13 12:00:00 | 12:00H - 18:00H | 2021-11-13 12:08:37
You can simply extract the hour and do some arithmetic:
select t.*,
floor(extract(hour from start_timestamp) / 6) * 6 as bin
from t;
Note: This characterizes the bin by the earliest hour. That seems more useful than a string representation, but you can construct a string if you really want.
I have some tables in a postgres that have a column for year and a column for quarter (both stored as bigint). I need to be able to combine those together in the output of a query in the form of 'YYYYQ' (not the hard part) AND have the datatype of that field be datetime (<--the hard part).
The only query I have attempted that didn't fail was -
SELECT to_date((year::VARCHAR + quarter::VARCHAR),'YYYYQ') AS Stuff
FROM company.products
And while the output is in DATETIME format, there is no Quarter info in it.
Sample -
stuff
2011-01-01
2011-01-01
2012-01-01
2012-01-01
2012-01-01
Is it even possible to create output that has the format 'YYYYQ' AND is in DATETIME format? And if so, how?
From the PostgreSQL docs (emphasis mine):
In to_timestamp and to_date, weekday names or numbers (DAY, D, and related field types) are accepted but are ignored for purposes of computing the result. The same is true for quarter (Q) fields.
You can save the date of the 1st day of the quarter. Multiply the recorded quarter -1 by 3.
SELECT to_date('2021','YYYY') + interval '6 month';
?column?
---------------------
2021-07-01 00:00:00
SELECT to_char(to_date('2021','YYYY') + interval '6 month','YYYYQ');
to_char
---------
20213
SELECT q,
to_char(to_date('2021','YYYY') + interval '3 month'*(q-1),'YYYYQ') as YYYYQ,
to_date('2021','YYYY') + interval '3 month'*(q-1) as d
FROM generate_series(1,4) f(q);
q | yyyyq | d
---+-------+---------------------
1 | 20211 | 2021-01-01 00:00:00
2 | 20212 | 2021-04-01 00:00:00
3 | 20213 | 2021-07-01 00:00:00
4 | 20214 | 2021-10-01 00:00:00
hello my friends I got tired of looking for a solution I have a postgresql database that has a timestamp column I want to extract the values this way
2010-01-01 14:34:43
without the milliseconds how to do this I want it
2010-01-01 14:34:43
and he shows me like this
2010-01-01 14:34:43.267543
If you want to discard the milliseconds you can use date_trunc():
date_trunc('second', mytimestamp)
On the other hand if you want to round to the closest second, you can cast to timestamp(0):
mytimestamp::timestamp(0)
Demo on DB Fiddle - I used a timestamp whose tens of seconds is greater than 5 to make the test representative:
select
mytimestamp,
date_trunc('second', mytimestamp) trunc_mytimestamp,
mytimestamp::timestamp(0) round_mytimestamp
from (values('2010-01-01 14:34:43.567543'::timestamp)) as t(mytimestamp)
mytimestamp | trunc_mytimestamp | round_mytimestamp
:------------------------- | :------------------ | :------------------
2010-01-01 14:34:43.567543 | 2010-01-01 14:34:43 | 2010-01-01 14:34:44
I have a set of data where one column is date and time. I have been asked for all the data in the table, between two date ranges and within those dates, only certain time scale. For example, I was data between 01/02/2019 - 10/02/2019 and within the times 12:00 AM to 07:00 AM. (My real date ranges are over a number of months, just using these dates as an example)
I can cast the date and time into two different columns to separate them out as shown below:
select
name
,dateandtimetest
,cast(dateandtimetest as date) as JustDate
,cast(dateandtimetest as time) as JustTime
INTO #Test01
from [dbo].[TestTable]
I put this into a test table so that I could see if I could use a between function on the JustTime column, because I know I can do the between on the dates no problem. My idea was to get them done in two separate tables and perform an inner join to get the results I need
from #Test01
WHERE justtime between '00:00' and '05:00'
The above code will not give me the data I need. I have been racking my brain for this so any help would be much appreciated!
The test table I am using to try and get the correct code is shown below:
|Name | DateAndTimeTest
-----------------------------------------|
|Lauren | 2019-02-01 04:14:00 |
|Paul | 2019-02-02 08:20:00 |
|Bill | 2019-02-03 12:00:00 |
|Graham | 2019-02-05 16:15:00 |
|Amy | 2019-02-06 02:43:00 |
|Jordan | 2019-02-06 03:00:00 |
|Sid | 2019-02-07 15:45:00 |
|Wes | 2019-02-18 01:11:00 |
|Adam | 2019-02-11 11:11:00 |
|Rhodesy | 2019-02-11 15:16:00 |
I have now tried and got the data to show me information between the times on one date using the below code, but now I would need to make this piece of code run for every date over a 3 month period
select *
from dbo.TestTable
where DateAndTimeTest between '2019-02-11 00:00:00' and '2019-02-11 08:30:00'
You can use SQL similar to following:
select *
from dbo.TestTable
where (CAST(DateAndTimeTest as date) between '2019-02-11' AND '2019-02-11') AND
(CAST(DateAndTimeTest as time) between '00:00:00' and '08:30:00')
Above query will return all records where DateAndTimeTest value in date range 2019-02-11 to 2019-02-11 and with time between 12AM to 8:30AM.
I have a table containing a datetime column and some misc other columns. The datetime column represents an event happening. It can either contains a time (event happened at that time) or NULL (event didn't happen)
I now want to count the number of records happening in specific intervals (15 minutes), but do not know how to do that.
example:
id | time | foreign_key
1 | 2012-01-01 00:00:01 | 2
2 | 2012-01-01 00:02:01 | 4
3 | 2012-01-01 00:16:00 | 1
4 | 2012-01-01 00:17:00 | 9
5 | 2012-01-01 00:31:00 | 6
I now want to create a query that creates a result set similar to:
interval | COUNT(id)
2012-01-01 00:00:00 | 2
2012-01-01 00:15:00 | 2
2012-01-01 00:30:00 | 1
Is this possible in SQL or can anyone advise what other tools I could use? (e.g. exporting the data to a spreadsheet program would not be a problem)
Give this a try:
select datetime((strftime('%s', time) / 900) * 900, 'unixepoch') interval,
count(*) cnt
from t
group by interval
order by interval
Check the fiddle here.
I have limited SQLite background (and no practice instance), but I'd try grabbing the minutes using
strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
with the %M modifier (http://souptonuts.sourceforge.net/readme_sqlite_tutorial.html)
Then divide that by 15 and get the FLOOR of your quotient to figure out which quarter-hour you're in (e.g., 0, 1, 2, or 3)
cast(x as int)
Getting the floor value of a number in SQLite?
Strung together it might look something like:
Select cast( (strftime( 'YYYY-MM-DD HH:MI:SS', your_time_field, '%M') / 15) as int) from your_table
(you might need to cast before you divide by 15 as well, since strftime probably returns a string)
Then group by the quarter-hour.
Sorry I don't have exact syntax for you, but that approach should enable you to get the functional groupings, after which you can massage the output to make it look how you want.