SQLITE multiple row values into columns - sqlite

I have event status table, the table structure is already defined, I would like to make several row value into one row.
current table data:
eventable:
EVENT EVENTNAME EVENTACTION STATUS TIMESTAMP
"Event1" "FootBall" "FootBall0" "started" "1554980085"
"Event1" "TableTennis" "TT0" "started" "1554980086"
"Event1" "FootBall" "FootBall0" "success" "1554980087"
"Event1" "Chess" "CHESS0" "success" "1554980095"
"Event1" "TableTennis" "TT0" "running" "1554980189"
"Event1" "FootBall" "FootBall1" "started" "1554980082"
I need to select query to display the data as follows:
EVENT EVENTNAME EVENTACTION STATUS STARTTIME RUNNINGTIME ENDTIME
"Event1" "FootBall" "FootBall0" "success" 1554980085 NULL 1554980087
"Event1" "TableTennis" "TT0" "running" 1554980086 1554980189 NULL
"Event1" "Chess" "CHESS0" "success" 1554980098 NULL 1554980100
I have to show the EVENT, EVENTNAME, EVENTACTION and latest STATUS and timestamp of started, running and success, If the time is not there then should set NULL.
I have used SELECT query with case but the timestamps doesn't place in single the relevant row.
SELECT AE.EVENT,
AE.EVENTNAME,
AE.EVENTACTION,
AE.STATUS,
(case WHEN AE.STATUS='started' THEN AE.timestamp END) as starttime,
(case WHEN AE.STATUS='running' THEN AE.timestamp END) as runningtime,
(case WHEN AE.STATUS in ('success','failed') THEN AE.timestamp END) as endtime
FROM agentEvents AE
ORDER by timestamp ASC
Any leads.

You need to aggregate by event, and then take the MAX of the CASE expressions:
SELECT
AE.EVENT,
AE.EVENTNAME,
AE.EVENTACTION,
MAX(CASE WHEN AE.STATUS = 'started' THEN AE.timestamp END) AS starttime,
MAX(CASE WHEN AE.STATUS = 'running' THEN AE.timestamp END) AS runningtime,
MAX(CASE WHEN AE.STATUS IN ('success', 'failed') THEN AE.timestamp END) AS endtime
FROM agentEvents AE
GROUP BY
AE.EVENT,
AE.EVENTNAME,
AE.EVENTACTION
ORDER BY
MAX(CASE WHEN AE.STATUS = 'started' THEN AE.timestamp END);
Note that it makes no sense to order by the timestamp column alone, because it no longer exists after aggregation. So, I order by the starting time instead. It also makes no sense to select the STATUS column, so I have removed it.

Related

Carry Forward values in Presto

I am using the below query to pivot my data and generate a CSV but the problem is I have a dataset in which the data points are coming in a scattered way with each timestamp.
with map_date as (
SELECT
vin,
epoch,
timestamp,
date,
map_agg(signalName, value) as map_values
from hive.vehicle_signals.vehicle_signals_flat
where date(date) = date('2020-03-12')
and date(cast(from_unixtime(epoch) as timestamp) - interval '0' hour) = current_date - interval '2' day
and vin = '000011'
and signalName in ('timestamp','epoch','msgId','usec','vlan','vin','msgName','value')
GROUP BY vin, epoch, timestamp, date
order by timestamp desc
)
SELECT
epoch
, timestamp
, CASE WHEN element_at(map_values, 'value') IS NOT NULL THEN map_values['value'] ELSE NULL END AS value
, vin
, current_date - interval '2' day AS date
from map_date
I get the following CSV as a result. Is there a way I can carry forward the value until a new value is found at a newer timestamp? Like in the image below the value '14.3' comes and the next value '16.5' comes after a few timestamps, How can I carry the value '14.3' till row 7th and repeat the logic on the entire column. How can I make my output field look like column 'G' in the image using Presto?
Thanks in advance!!
You can use a mysql #variable to store the last value, for example:
SELECT
epoch
, timestamp
, CASE WHEN element_at(map_values, 'value') IS NOT NULL THEN #last_value:= map_values['value'] ELSE #last_value END AS value
, vin
, current_date - interval '2' day AS date
from map_date, (select #last_value:=0) v
The last part, (select #last_value:=0) v is to initialize the #last_value variable.
A basic tutorial
https://www.mysqltutorial.org/mysql-variables/
More advanced tutorial with additional info
https://www.xaprb.com/blog/2006/12/15/advanced-mysql-user-variable-techniques/

Redshift Error when adding date to a time stamp using case statement

I am trying to have a CASE statement that adds days to a time stamp column.
select cust_id,
case when type = 'a' then (created_date - INTERVAL '7 DAY')
when type = 'b' then (created_date - INTERVAL '10 DAY')
else 0 end as date_when_breach
from table
The above throws an error
Reason:
SQL Error [42804]: ERROR: CASE types integer and timestamp without time zone cannot be matched
Sample created_date value is 2019-02-14 11:16:16
Your CASE statement is not consistent with return types - first two branches return a DATE and the ELSE returns an INTEGER. Change your ELSE to return DATE (eg.current_date, depends on what you want to achieve) or NULL (or just remove it, which will have the same effect).
select
cust_id,
case
when type = 'a' then (created_date - INTERVAL '7 DAY')
when type = 'b' then (created_date - INTERVAL '10 DAY')
else NULL
end as date_when_breach
from table

Oracle to_date return incorrect result

I have a table 4 columns - Code, Status, EffectiveDate (EFF_DT), EndDate (END_DT). All the columns are Varchar2 type. EFF_DT and END_DT has ISO format date (YYYY-MM-DD) with NULL values for few rows. Need to get the rows which has END_DT greater than today's date.
While executing the below query, it returns all the Not NULL rows for END_DT. Do not compare the END_DT at all.
select code, status, EFF_DT, END_DT
from (
select CODE, EFF_DT, Status,to_date("END_DT" ,'YYYY-MM-DD' ) as END_DT
from xxx.ZZZ
) TAB
where to_date(TAB.END_DT ,'DD-MM-YY' ) > to_date(CAST(CURRENT_TIMESTAMP as Date), 'DD-MM-YY')
ORDER BY 1 ASC
But the below query compares the END_DT and returns the result properly -
SELECT "TAB"."CODE" , "TAB"."STATUS" AS "STATUS" , "TAB"."EFF_DT" , "TAB"."END_DT"
FROM xxx.ZZZ "TAB"
WHERE ( (to_date("TAB"."END_DT",'YYYY-MM-DD') > to_date(CAST(CURRENT_TIMESTAMP as Date), 'YY-MM-DD')) )
ORDER BY 1 ASC
What is going wrong with the 1st query?
I see difference in return value of END_DT.
For the 1st query, the data is coming like -
while as for the 2nd query, the data is coming like

substring: row information to field names

I have information in an SQLite database. The database structure can not be changed.
I am trying to construct a query that will give me a result in which the TypeOfInformation entries are field names:
My first try was to work with subqueries:
SELECT (SELECT Value FROM FinData WHERE Type = 'Price') AS Price,
(SELECT Value FROM FinData WHERE Type = 'Volume') AS Volume
FROM FinData")
Seemed perfect, however, the result was a resultset in which EVERY entry in the columns Price and Volume are equal to the FIRST respective entry of Price and Volume in the original database:
I tried to get around this and to include the other Price and Volume information ­- but I failed. (Which is a pity, because the syntax seemed somehow easy to grasp.)
Next try was the following:
Select Date, Value AS Volume From FinData WHERE Volume IN
(SELECT Value FROM FinData WHERE (Type = 'Volume'))
This gives me a resultset with a Volume column and all volume information. Okay, so far. However, when I want to complement this resultset which a Price column via
Select Date, Value AS Volume From FinData WHERE Volume IN
(SELECT Value FROM FinData WHERE (Type = 'Volume'))
union
Select Date, Value AS Close From FinData WHERE Price IN
(SELECT Value FROM FinData WHERE (Type = 'Price'))
I get a resultset that shows Price and Volume information in only ONE column ("Volume"), which therefore is also useless.
To look up a value corresponding to a row in the outer query, you have to use a correlated subquery, which explicitly makes a connection between both:
SELECT Date,
(SELECT Value
FROM FinData
WHERE Date = Dates.Date
AND TypeOfInformation = 'Price'
) AS Price,
(SELECT Value
FROM FinData
WHERE Date = Dates.Date
AND TypeOfInformation = 'Volume'
) AS Volume
FROM (SELECT DISTINCT Date
FROM FinData) AS Dates;
(The DISTINCT subquery is used to prevent multiple rows for each date.)
Alternatively, group all rows for a date, and use aggregation functions and CASE expressions to extract the values from the proper rows:
SELECT Date,
MAX(CASE WHEN TypeOfInformation = 'Price' THEN Value END) AS Price,
MAX(CASE WHEN TypeOfInformation = 'Volume' THEN Value END) AS Volume
FROM FinData
GROUP BY Date;
Assuming dates are unique per price volume pair, you can do this:
with xxx(date,price,volume) as
(
select date,value,0 from findata where typeofinformation = 'Price'
union
select date,0,value from findata where typeofinformation = 'Volume'
)
select date,sum(price) price,sum(volume) volume from xxx group by date;

AgeCalendar Datetime Field Issue

For my AgingCalendar field, I have 3 conditions using CASE WHEN:
CASE WHEN A.[END_DTTM] > A.[STRT_DTTM] THEN C2.[DY_OF_CAL_NUM] - C1.[DY_OF_CAL_NUM]
WHEN A.[END_DTTM] IS NULL and A.[STRT_DTTM] IS NOT NULL THEN C3.[DY_OF_CAL_NUM] - C1.[DY_OF_CAL_NUM]
WHEN A.[END_DTTM] = A.[STRT_DTTM] THEN 1
END AS AgeCalendar
For my third condition, I'm trying to basically say when the End Datetime = Start Datetime, the age in Calendar days should be set to 1 calendar day.
However, in some of the records I'm bringing in, the start date equals the end date, but the times associated with each datetime are different. When this happens, those records are receiving a NULL in the AgeCalendar field.(For example I could have 6/6/2014 0:00:00 = 6/6/2014 0:00:00, and that will give me 1...but if I had 6/6/2014 0:00:00 = 6/6/2014 0:03:59 (or something like that)...it'll give me a NULL value because it's not matching.
How can I update the code above so that I'm basically saying when End Date = Start Date, then 1...regardless of not having matching times?
CASTor CONVERT them as dates to ignore the time.
WHEN CONVERT(DATE, A.[END_DTTM]) = CONVERT(DATE, A.[STRT_DTTM]) THEN 1
OR
WHEN CAST(A.[END_DTTM] AS DATE) = CAST(A.[STRT_DTTM] AS DATE) THEN 1

Resources