DATE_PART and Postgresql - sql

I have a problem when I subtract two date in a function DATE_PART in this query.
SELECT
TO_CHAR(date_trunc('month',sql_activity_days.created_month),'YYYY-MM') AS "sql_activity_days.created_month",
coalesce(SUM(
CASE
WHEN(date_part('day', (sql_activity_days.sale_date + 1) - sql_activity_days.start_date) < 122)
THEN sql_activity_days.cad_net_invoiced
ELSE NULL
END
),0) AS "sql_activity_days.activity_over_122_day_after_signup"
FROM
camel.f_subscription_touch AS subscription_touch
LEFT JOIN sql_activity_days ON subscription_touch.id = sql_activity_days.customer_id
group by date_trunc('month',sql_activity_days.created_month)
order by 1 desc limit
500
The PostgreSQL database encountered an error while running this query.
ERROR: function date_part(unknown, integer) does not exist Hint: No
function matches the given name and argument types. You might need to
add explicit type casts. Position: 1340

The second argument of the function date_part can be either a timestamp or an interval.
Your expression (sql_activity_days.sale_date + 1) - sql_activity_days.start_date subtracts two dates, whose resulting datatype is an integer, hence the error.
The solution to this would be to remove date_part and use the expression directly. The difference of two dates always gives the value in days.

Related

What causes error "Strings cannot be added or subtracted in dialect 3"

I have the query:
WITH STAN_IND
AS (
SELECT ro.kod_stanow, ro.ind_wyrob||' - '||ro.LP_OPER INDEKS_OPERACJA, count(*) ILE_POWT
FROM M_REJ_OPERACJI ro
JOIN M_TABST st ON st.SYMBOL = ro.kod_stanow
WHERE (st.KOD_GRST starting with 'F' or (st.KOD_GRST starting with 'T') ) AND ro.DATA_WYKON>'NOW'-100
GROUP BY 1,2)
SELECT S.kod_stanow, count(*) ILE_INDEKS, SUM(ILE_POWT-1) POWTORZEN
from STAN_IND S
GROUP BY S.kod_stanow
ORDER BY ILE_INDEKS
That should be working, but I get an error:
SQL Error [335544606] [42000]: Dynamic SQL Error; expression evaluation not supported; Strings cannot be added or subtracted in dialect 3 [SQLState:42000, ISC error code:335544606]
I tried to cast it into bigger varchar but still no success. What is wrong here? Database is a Firebird 2.1
Your problem is 'NOW'-100. The literal 'NOW' is not a date/timestamp by itself, but a CHAR(3) literal. Only when compared to (or assigned to) a date or timestamp column will it be converted, and here the subtraction happens before that point. And the subtraction fails, because subtraction from a string literal is not defined.
Use CAST('NOW' as TIMESTAMP) - 100 or CURRENT_TIMESTAMP - 100 (or cast to DATE or use CURRENT_DATE if the column DATA_WYKON is a DATE).

FETCH the latest partition from HIVE table

Hi I am very much new to this.
I have three columns YEAR, MONTH,DAY in INTEGER format.
I want to load the script and combine YEAR,MONTH,DAY as single column and fetch the maximum.
I tried like,
Load year,month,date from HIVE.`abc`.`abc1';
SELECT max(cast(year as String) || '_' || cast(month as string) || '_' || cast(day as string)) as result FROM HIVE.`abc`.`abc1';
By doing this I will get the result as 2020_5_21. But I should use the separator and find the max of the date.
The following error occurred: Connector reply error: SQL##f -
SqlState: S1000, ErrorCode: 35, ErrorMsg: [Cloudera][Hardy] (35) Error
from server: error code: '1' error message: 'Error while compiling
statement: FAILED: Execution Error, return code 1 from
org.apache.hadoop.hive.ql.exec.tez.TezTask'.
I want to use the result in WHERE clause. But I don't know the statement.
SQL select * from HIVE.abc.`abc1' where ---- ;
Please help.
If month and day are stored as integers, you need to use lpad() to add zero if it is single digit month or day. For example month 5 should become 05. Without this max may work incorrectly. Also use dash as a separator to have date in compatible format.
max(concat(year,'-',lpad(month, 2,0),'-',lpad(day, 2,0)))
And to use it in the WHERE use WHERE date in (select max ...):
SELECT * from your_table
WHERE concat(year,'-',lpad(month, 2,0),'-',lpad(day, 2,0)) in (select max(concat(year,'-',lpad(month, 2,0),'-',lpad(day, 2,0))) from your_table)
Also you may need to quote names like year, month, day in backticks everywhere in sql:
max(concat(`year`,'-',lpad(`month`, 2,0),'-',lpad(`day`, 2,0)))

Division of dates to create percentage SQL

I am trying to do write in a function to subtract a few dates, then divide them together, add 1 then * 100 to get an overall % complete.
((SYSDATETIME() - proj.proj_scheduledDate)/(proj.proj_dueDate - proj.proj_scheduledDate + 1)) * 100 as 'percent done
returns
Operand data type datetime is invalid for divide operator.
What do I need to do to get this query to work? THANKS!
Might I suggest using DATEDIFF() with dd for a day datepart -- you can easily get the percentage of days completed - or go to smaller datepart values if you need to.
Returns the count (signed integer) of the specified datepart
boundaries crossed between the specified startdate and enddate.
SELECT
FLOOR((DATEDIFF(NOW(), proj.proj_scheduledDate) / DATEDIFF(proj.proj_dueDate, proj.proj_scheduledDate)) * 100)
FROM
foo;

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.

DB2 UDF to return added date?

I am trying to make a DB2 UDF that takes input a date and returns new date with some months added to it. The query syntax for this step is to use
select date + 12 months from sysibm.sysdummy1;
Inside the UDF I can't get this to work
monthsToAdd INTEGER;
SET monthsToAdd=4;
set result= inputDate + monthsToAdd + MONTHS;
return result;
It says
SQL State: 42816
Vendor Code: -182
Message: [SQL0182] A date, time, or timestamp expression not valid. Cause . . . . . : One of the following has occurred: -- An operand of addition is a date and the other is not a date duration. -- An operand of addition is a time and the other is not a time duration. -- An operand of addition is a timestamp and the other is not a duration. -- An operand of subtraction is a date and the other is not a date, character, or date duration. -- An operand of subtraction is a time and the other is not a time, character, or time duration. -- An operand of subtraction is a timestamp and the other is not a timestamp, character, or duration. Recovery . . . : Correct the arithmetic expression so that it contains a valid date, time, or timestamp expression. Try the request again.
It's a simple fix:
set result = inputDate + monthsToAdd MONTHS;
As actually scripted on a v5r3 DB2 for i5/OS [and also with DB2 for IBM i 7.3]:
create function add_months
( inputDate DATE
, monthsToAdd INTEGER
) returns DATE
language SQL DETERMINISTIC
RETURN inputDate + monthsToAdd MONTHS
select add_months(date'2016-04-12', 6)
from sysibm.sysdummy1
-- likeness of a report from above query follows:
ADD_MONTHS
2016-10-12