SQL WHERE with multiple conditions: shortcut? - sql

I'm trying to find an average temperature on days that are Saturday or Sunday using SQL. I realize a possible solution is:
SELECT avg(cast(meantempi as integer))
FROM weather_data
WHERE cast (strftime('%w', date) as integer) = 0 or
cast (strftime('%w', date) as integer) = 6
However, I am curious as to whether there is an optimal shortcut possible after my WHERE statement in this particular situation.
In other words, is there an equivalent to doing the preceding problem as:
SELECT avg(cast(meantempi as integer))
FROM weather_data
WHERE cast (strftime('%w', date) as integer) = 0 or 6

You can use in:
SELECT avg(cast(meantempi as integer))
FROM weather_data
WHERE cast (strftime('%w', date) as integer) IN (0, 6)

Related

Convert query Teradata to Hive

i have the following query and it executes successfully in teradata.
CASE
WHEN Cast(STG_101_118_INVM.ACCT_OPEN_DT AS INTEGER) > 2956565 THEN Cast('2999-12-31'AS DATE)
WHEN Cast(STG_101_118_INVM.ACCT_OPEN_DT AS INTEGER) = 0 THEN Cast('1900-01-01' AS DATE)
ELSE Cast('1900-01-01' AS DATE) + Cast(STG_101_118_INVM.ACCT_OPEN_DT AS INTEGER) - 1 END
AS ACCT_OPEN_DT
i have the following query and it executes successfully in teradata.
but when run on hive it doesn't work and it shows a warning like this.
Error while compiling statement: FAILED: SemanticException line
0:undefined:-1 Wrong arguments 'ACCT_OPEN_DT': No matching method for
class org.apache.hadoop.hive.ql.udf.generic.GenericUDFOPDTIPlus with
(date, int)
what should i change?
can you help me to convert this query to hive format?
You have to use date_add() to add ACCT_OPEN_DT INT to a date. You can use below SQL -
CASE
WHEN Cast(STG_101_118_INVM.ACCT_OPEN_DT AS INTEGER) > 2956565 THEN Cast('2999-12-31'AS DATE)
WHEN Cast(STG_101_118_INVM.ACCT_OPEN_DT AS INTEGER) = 0 THEN Cast('1900-01-01' AS DATE)
ELSE DATE_ADD(Cast('1900-01-01' AS DATE) ,Cast(STG_101_118_INVM.ACCT_OPEN_DT AS INTEGER) - 1) END
AS ACCT_OPEN_DT

How to convert an int to DateTime in BigQuery

I have an INT64 column called "Date" which contains many different numbers like: "20210209" or "20200305". I want to turn those numbers into a date with this format: MM-YYYY (so in these cases, 02-2021 and 03-2020). Ultimately I want to sum all the data in each month together. The problem is that BigQuery can't convert INT64 to date, only to strings. I'm not sure if I should convert to a string and then to a date or if there is a better way.
Although converting to a string then a date both works and is very concise, over large enough numbers of rows (which may be the case in Big Query) you may be better off using integer maths and using DATE(year, month, day)...
https://cloud.google.com/bigquery/docs/reference/standard-sql/date_functions#date
SELECT
DATE(
DIV( 20210209 , 10000), -- Which gives 2021
DIV(MOD(20210209, 10000), 100), -- Which gives 02
MOD(20210209, 100) -- Which gives 09
)
You can convert the value to a string and use parse_date():
select parse_date('%Y%m%d', cast(20210209 as string))
Another option
select date,
regexp_replace('' || date, r'(\d{4})(\d{2})(\d{2})', r'\2-\1') as MM_YYYY
from your_table
if applied to sample data in your question - output is
Yet another option
select date,
format_date('%m-%Y', parse_date('%Y%m%d', '' || date)) as MM_YYYY
from your_table
with same output

Date to Integer YYYMMDD in Standar SQL (BigQuery)

I need to convert a date to an integer with the format YYYMMDD in Bigquery.
I tried with:
PARSE_DATE('%Y%m%d', response_date)
but its not working (Error: No matching signature for function PARSE_DATE for argument types: STRING, DATE. Supported signature: PARSE_DATE(STRING, STRING) at [1:8])
response_date: Date Format
Wanted Result: 20210201 as an integer or string
If anyone know the correct sintax it would be really helpful. Thank you!
One method is arithmetic:
select extract(year from response_date) * 10000 + extract(month from response_date) * 100 + extract(day from response_date)
Another method is FORMAT_DATE():
select cast(format_date('%Y%m%d', response_date) as int64)
Another option (might look funny/silly but works)
select translate('' || response_date, '-', '')
and then you can do with resulted string whatever cast'ing you need or just leave as is (as string)
... can easily be tested with below query
select translate('' || current_date(), '-', '')
with output
But obviously - the best way to go is with FORMAT_DATE() as in Gordon's answer :o)

Convert an Integer to time

I am being supplied a single integer that is supposed to represent an hour. So If it returns 1 it is 1:00 am and so forth on a 24 hour clock,13 for example is 1:00 pm. I need to convert this into time in SQL.
I know in MYSQL they have a function which does this:
SEC_TO_TIME(TheHour*60*60)
Is there an equivalent I can use in SQL? How do I do this?
You could do something like this.
select cast(DATEADD(hour, 13, 0) as time)
The upside is that it will still work even with negative numbers or values over 24.
There are two T-SQL function:
DATEFROMPARTS ( year, month, day )
and
TIMEFROMPARTS ( hour, minute, seconds, fractions, precision )
then you can use CONVERT if you need to format it.
-- test data
declare #hour_table table(hour_number int)
while (select count(*) from #hour_table) < 24
begin
insert into #hour_table(hour_number)
select count(*) from #hour_table
end
-- return results with your conversion to time string
select
hour_number,
convert(varchar(8),timefromparts( hour_number, 0, 0, 0, 0 ),0) as time_string
from #hour_table

Date arithmetic in SQL on DB2/ODBC

I'm building a query against a DB2 database, connecting through the IBM Client Access ODBC driver. I want to pull fields that are less than 6 days old, based on the field 'a.ofbkddt'... the problem is that this field is not a date field, but rather a DECIMAL field, formatted as YYYYMMDD.
I was able to break down the decimal field by wrapping it in a call to char(), then using substr() to pull the year, month and day fields. I then formatted this as a date, and called the days() function, which gives a number that I can perform arithmetic on.
Here's an example of the query:
select
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM-
concat substr(char(a.ofbkddt),7,2) ) as difference, -- DD
a.ofbkddt as mydate
from QS36F.ASDF a
This yields the following:
difference mydate
2402 20050402
2025 20060306
...
4 20110917
3 20110918
2 20110919
1 20110920
This is what I expect to see... however when I use the same logic in the where clause of my query:
select
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM-
concat substr(char(a.ofbkddt),7,2) ) as difference, -- DD
a.ofbkddt as mydate
from QS36F.ASDF a
where
(
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM
concat substr(char(a.ofbkddt),7,2) ) -- DD
) < 6
I don't get any results back from my query, even though it's clear that I am getting date differences of as little as 1 day (obviously less than the 6 days that I'm requesting in the where clause).
My first thought was that the return type of days() might not be an integer, causing the comparison to fail... according to the documentation for days() found at http://publib.boulder.ibm.com/iseries/v5r2/ic2924/index.htm?info/db2/rbafzmst02.htm, it returns a bigint. I cast the difference to integer, just to be safe, but this had no effect.
You're going about this backwards. Rather than using a function on every single value in the table (so you can compare it to the date), you should pre-compute the difference in the date. It's costing you resources to run the function on every row - you'd save a lot if you could just do it against CURRENT_DATE (it'd maybe save you even more if you could do it in your application code, but I realize this might not be possible). Your dates are in a sortable format, after all.
The query looks like so:
SELECT ofbkddt as myDate
FROM QS36F.ASDF
WHERE myDate > ((int(substr(char(current_date - 6 days, ISO), 1, 4)) * 10000) +
(int(substr(char(current_date - 6 days, ISO), 6, 2)) * 100) +
(int(substr(char(current_date - 6 days, ISO), 9, 2))))
Which, when run against your sample datatable, yields the following:
myDate
=============
20110917
20110918
20110919
20110920
You might also want to look into creating a calendar table, and add these dates as one of the columns.
What if you try a common table expression?
WITH A AS
(
select
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM-
concat substr(char(a.ofbkddt),7,2) ) as difference, -- DD
a.ofbkddt as mydate
from QS36F.ASDF a
)
SELECT
*
FROM
a
WHERE
difference < 6
Does your data have some nulls in a.ofbkddt? Maybe this is causing some funny behaviour in how db2 is evaluating the less than operation.