Error in plpgsql function: array value must start with "{" or dimension information - function

I'm trying to format the results of this query:
CREATE OR REPLACE FUNCTION "alarmEventList"(sampleid integer
, starttime timestamp without time zone
, stoptime timestamp without time zone)
RETURNS text[] AS
$BODY$DECLARE
result text[];
BEGIN
select into result array_agg(res::text)
from (
select to_char("Timestamp", 'YYYY-MM-DD HH24:MI:SS')
,"AlertLevel"
,"Timestamp" - lag("Timestamp") over (order by "Timestamp")
from "Judgements"
WHERE "SampleID" = sampleid
and "Timestamp" >= starttime
and "Timestamp" <= stoptime
) res
where "AlertLevel" > 0;
select into result array_to_string(result,',');
return result;
END
$BODY$
LANGUAGE plpgsql VOLATILE
Right now without array_to_string() I get something like this:
{"(\"2013-10-16 15:10:40\",1,00:00:00)","(\"2013-10-16 15:11:52\",1,00:00:48)"}
and I want something like this:
2013-10-16 15:10:40,1,00:00:00 | 2013-10-16 15:11:52,1,00:00:48 |
But when I run the query I get error:
array value must start with "{" or dimension information

You do not actually want an array type, but a string representation.
Can be achieved like this:
CREATE OR REPLACE FUNCTION "alarmEventList"(sampleid integer
, starttime timestamp
, stoptime timestamp
, OUT result text) AS
$func$
BEGIN
SELECT INTO result string_agg(concat_ws(','
,to_char("Timestamp", 'YYYY-MM-DD HH24:MI:SS')
,"AlertLevel"
,"Timestamp" - ts_lag)
, ' | ')
FROM (
SELECT "Timestamp"
,"AlertLevel"
,lag("Timestamp") OVER (ORDER BY "Timestamp") AS ts_lag
FROM "Judgements"
WHERE "SampleID" = sampleid
AND "Timestamp" >= starttime
AND "Timestamp" <= stoptime
) res
WHERE "AlertLevel" > 0;
END
$func$ LANGUAGE plpgsql
The manual on string_agg() and concat_ws().

Related

Validating age using a function in MySQL

so i'm having some issues using a function in SQL where i calculate the age given a certain date. The thing is that i need to validate with the current date and the date of birth if it's already the year or not.
For example the date i have in a register is 1994-11-15 and when consulting the information with
select EmployeeID Num_Emloyee, concat(FirstName, " . ", LastName) Name_Employee, Title Puesto, fn_Age(BirthDate) Edad, fn_Age(HireDate) WorkYears
from employees;
It returns 24, however if i only consult with select the function it returns 23, the correct answer.
At the moment this is the function i'm using to validate the age is this:
create function fn_Age(dateVal date)
returns int
begin
declare age int;
if day(now()) and month(now()) >= day(dateVal) and month(dateVal) then
set age=year(now())-year(dateVal);
else
set age=(year(now())-year(dateVal)) - 1;
end if;
return age;
end
Is there anything i'm not considering in the function?
day(now()) and month(now()) >= day(dateVal) and month(dateVal)
This logic doesn't make sense. I don't know if an if supports tuples in MySQL. If so, you can do:
(month(now()), date(now())) >= ( month(dateval), day(dateval) )
(this works in a MySQL WHERE clause.)
You can also do:
month(now()) * 100 date(now()) >= month(dateval) * 100 + day(dateval)
You can also use timestampdiff-function
select timestampdiff(year, '1994-11-15', now());

Convert SQL FUNCTION to MySQL

I need to convert the following Function of SQL Server To MySQL. I am new to MySQL. Help needed.
the Function returns a generated Id based on the date :
-S1 or S2 ..S5 : the letter S followed by the number of week on month start from monday
-0X the month in two digits
-15 the year in two digits
Ex :
2015/06/01 to 2015/06/07 is S10615
2015/06/29 to 2015/07/05 is S50615
2015/07/06 to 2015/07/12 is S10715
Function
Create Function GetIdPanier()
Returns Varchar(25)
As
Begin
declare #week varchar(2) = DATEPART(DAY, DATEDIFF(DAY, 0, GETDATE())/7 * 7)/7 + 1
declare #month int = case when DATEPART(DAY,GETDATE()) < 7 and #week > 1
then DATEPART(MONTH,DATEADD(MONTH,-1,GETDATE()))
else DATEPART(MONTH,GETDATE())
end
return 'S' + #week + RIGHT('00' + CAST(#month AS varchar(2)), 2) + RIGHT(CAST(DATEPART(yyyy, GETDATE()) AS varchar(4)), 2)
End
MYSQL have function EXTRACT (like DatePart in MS SQL).
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_extract

select first day of previous month from record in sql server

I have a table that has a column called StartDateTime that stores datetime values. I need a statement that will return the date of the first day in the previous month of the current record. So, if the stored date is 2006-06-17 08:23:42.000 the statement would return 2006-05-01 00:00:00.000 and importantly if the stored date is 2006-01-17 08:23:42.000 the statement would return 2005-11-1 00:00:00.000
If I could use DATEBYPARTS this seems like it would be simple, but unfortunately I can not.
I tried using
CAST(
CAST( Year([StartDateTime]) as varchar(4) )
+ '-' +
CAST( (Month([StartDateTime])-1) as varchar(2) )
+ '-' +
CAST( '1' as varchar(2) )
AS DATETIME )
but it errors on January 1st dates and gives error "The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value."
select dateadd(mm, datediff(mm, 0, StartDateTime) - 1, 0)
from <yourtable>
Or, as Aaron Bertrand suggested in comments, more clear way
select dateadd(month, datediff(month, 0, StartDateTime) - 1, 0)
from <yourtable>
SQL FIDDLE EXAMPLE

Hundred year date conversion in ssis derived column

I'm trying to convert a Hundred Year Date (HYD) format to a regular date format through SSIS derived column transform. For example: Convert 41429
to 06/04/2013. I can do it with formatinng code within a script (and maybe I simply have to go this route) but feel there has to be a way to do so within a derived column that I'm just not getting. Any help is appreciated.
This is what I came up with. Are you sure your conversion is correct? My answer is 1 day. off.
DECLARE #t1 as date = '01/01/1900';
DECLARE #t2 as DATE = '12/31/1900';
DECLARE #hyd as INT;
-- This example shows that we need to add 1
SELECT #hyd = DATEDIFF (d, #t1, #t2) + 1 -- 364 + 1
SELECT #hyd
set #t2 = '06/04/2013';
SELECT #hyd = DATEDIFF (d,#t1, '06/04/2013') + 1-- 41427
SELECT #hyd
SELECT DATEADD (d, #hyd, '01-JAN-1900')
SELECT DATEADD (d, 41429, '01-JAN-1900')
A hundred year date is a calculation based on the number of days since 1899-12-31. It's an "Excel Thing". It also has a bug in it that you must account for.
The equivalent TSQL logic would be
DECLARE
#HYD int = 41429;
SELECT
#HYD =
CASE
WHEN #HYD > 60
THEN #HYD -1
ELSE
#HYD
END;
SELECT
DATEADD(d, #HYD, '1899-12-31') AS HYD;
Armed with that formula, I can write the following Expression in a Derived Column Transformation (assuming you have a column named HYD)
(HYD > 60) ? DATEADD("d",HYD - 1,(DT_DATE)"1899-12-31") : DATEADD("d",HYD,(DT_DATE)"1899-12-31")
And the results
--or inline SQL...using this
SELECT
case when ([HYD] > 60) then
DATEADD(day,[HYD] - 1,'1899-12-31')
else
DATEADD(day,[HYD],'1899-12-31')
end 'HYD_conv'
FROM
TableName
--and in the where clause if you like...
WHERE
(case when ([HYD] > 60) then DATEADD(day,[HYD] - 1,'1899-12-31') else DATEADD(day,[HYD],'1899-12-31') end) = '2016-01-14'

Convert seconds to human readable time duration

How would I best convert 90060 (seconds) to a string of "25h 1m"?
Currently I'm doing this in SQL:
SELECT
IF(
HOUR(
sec_to_time(
sum(time_to_sec(task_records.time_spent))
)
) > 0,
CONCAT(
HOUR(sec_to_time(sum(time_to_sec(task_records.time_spent)))),
'h ',
MINUTE(sec_to_time(sum(time_to_sec(task_records.time_spent)))),
'm'
),
CONCAT(
MINUTE(sec_to_time(sum(time_to_sec(task_records.time_spent)))),
'm'
)
) as time
FROM myTable;
But I'm not sure it's the most convenient method :-)
I'm open to suggestions on doing this both in SQL (differently than I'm already doing) or in PHP.
EDIT:
Examples of desired strings: "5m", "40m", "1h 35m", "45h" "46h 12m".
TIME_FORMAT(SEC_TO_TIME(task_records.time_spent),'%Hh %im')
Documentation is your friend:
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
According to comment:
DROP FUNCTION IF EXISTS GET_HOUR_MINUTES;
CREATE FUNCTION GET_HOUR_MINUTES(seconds INT)
RETURNS VARCHAR(16)
BEGIN
DECLARE result VARCHAR(16);
IF seconds >= 3600 THEN SET result = TIME_FORMAT(SEC_TO_TIME(seconds),'%kh %lm');
ELSE SET result = TIME_FORMAT(SEC_TO_TIME(seconds),'%lm');
RETURN result;
END
DELIMETER ;
Usage:
SELECT GET_HOUR_MINUTES(task_records.time_spent) FROM table
you can use predefined function sec_to_time()
sec_to_time(number_of_seconds)
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_sec-to-time
Try out this trick (on MySQL)
select date_format("1970-01-01 00:00:00" + interval <value_here> second, "%H:%i:%S")
SEC_TO_TIME sometime produces wrong values
try this: (input your pure seconds time)
var hours = Math.floor(input/3600);
var minutes = Math.floor((input-hours*3600)/60);
var seconds = input-(minutes*60)-(hours*3600);
function convertTime(){
return hours":"minutes":"seconds;
}