Esper: "time_order" seems not working - complex-event-processing

I'm using Esper (the event processing engine), the EPL query is:
select * from Event.ext:time_order(timestamp_event, 10000 minutes) where duration > 10
But the output is not ordered by "timestamp_event":
id int = 1, timestamp_event= 1412686800000, duration = 30
id int = 4, timestamp_event= 1412685900000, duration = 70
id int = 2, timestamp_event= 1412688600000, duration = 45
id int = 3, timestamp_event= 1412689500000, duration = 60
id int = 5, timestamp_event= 1412636400000, duration = 15
Why does not the "time_order(timestamp_event, 10000 minutes)" instruction work?
I think the problem is on Esper configuration, let's consider a simple query:
select * from Event.win:time(10 sec) order by id_event
This is the code of the "upate" method of the UpdateListener:
public void update(EventBean[] newEvents, EventBean[] oldEvents) {
EventBean event = newEvents[0];
System.out.println("id int = " + event.get("id_event") + ", timestamp_event = " + ((Long)event.get("timestamp_event")).toString());
But the output is non ordered by "id_event"!
id event = 1, timestamp_event = 1412686800000
id event = 4, timestamp_event = 1412687700000
id event = 2, timestamp_event = 1412687100000
id event = 3, timestamp_event = 1412687400000
id event = 5, timestamp_event = 1412688000000
It seems neither the "order by" instruction doesn't work, how is it possible?

The documentation says to select rstream as the events leaving are ordered and not events entering. See http://esper.codehaus.org/esper-5.0.0/doc/reference/en-US/html_single/index.html#view-time-order

You need to define some sort of time or length constrain. Your statement is simply returning all the entering events into the time_order window.
A statement like this for example would give you all the events in the right order, every 1 minute:
select * from Event.ext:time_order(timestamp_event, 10000 minutes)
where duration > 10 output snapshot every 1 minute
Or, you could define a data window and insert events into it like this:
create window OrderedEvents.ext:time_order(timestamp_event, 10000 minutes) as select * from Event;
insert into OrderedEvents select * from Event;
You can then use ad-hoc queries against it, and they will return the events in the correct order (although you could achieve the same with a win:time(10000 minutes) and adding an order by timestamp_event to your ad-hoc query).

Related

Entity Framework equivalent of datepart(qq, getdate)

I have the following SQL query which I want to translate to EF query
Select Year(_r.IssueDate) as Year, datepart(qq, _r.IssueDate) as Quarter,count(*) as TotalBillableRecords, SUM(_r.BillableHours) as TotalHOurs
FROM
(select _b.Name, _i.IssueDate, _ie.BillableHours from Beneficiaries _b
join [Beneficiaries.Invoices] _i on _b.Id = _i.BeneficiaryId
join [Beneficiaries.Invoices.Entries] _ie on _ie.InvoiceId = _i.Id
where BeneficiaryId = 1) as _r
group by Year(_r.IssueDate), datepart(qq, _r.IssueDate)
This results in this
And this is what I would also want to have in my linq expression
How can I translate this to EF query ? I've tried like so
var query =
from beneficiary in _dbContext.Beneficiaries
where beneficiary.Id == beneficiaryId
from invoice in beneficiary.Invoices
//where invoice.IssueDate >= since
//where invoice.IssueDate.Month > notBefore && invoice.IssueDate.Month <= notAfter
from invoiceEntry in invoice.InvoiceEntries
group new
{
beneficiary,
invoiceEntry,
}
by new
{
Year = beneficiary.InvoiceMeta.IssueDate.Year,
Quarter = (beneficiary.InvoiceMeta.IssueDate.Month - 1) / 3 + 1,
}
into #group
select new
{
Year = #group.Key.Year,
Quarter = #group.Key.Quarter,
Hours = #group.Sum(x => x.invoiceEntry.BillableHours),
};
var y = query.ToList();
But the result is as following
[0] = Quarter = 3, Year = 2022, Hours = 6729.0
And this is it, only one entry.
What I'm noticing is that it only takes the last quarter composed of 3 months, (because the last would be the one which is not finished yet)
The class hierarchy is
Beneficiary 1-* Invoice 1-* Entries

How to summarize DateTime-fields in EF6

again, I'm struggeling with Linq or EF6.
I have a table with columns (DateTime)[BeginOfWork] and (DateTime)[EndOfWork].
Now, I need to substract the BeginOfWork-value from the EndOfWork-value. From this result, I need to build a total sum.
In SQL, it looks like this:
SELECT Timesheets.EmployeeId, Sum(DateDiff("h",[Timesheets].[BeginOfWork],[Timesheets].[EndOfWork])) AS HoursOfWork
FROM Timesheets
GROUP BY Timesheets.EmployeeId
HAVING (((Timesheets.EmployeeId)=1));
How do I do this in EF6?
Actually, not working some variations of that:
int employeeId = 1;
var timesheetSum = (from ts in db.Timesheets
where (ts.EmployeeId == employeeId)
select new
{
hoursOfWork = DbFunctions.DiffHours(ts.BeginOfWork, ts.EndOfWork)
}).Sum(ts => ts.hoursOfWork);
The above results in integer rounded hoursOfWork, that don't include minutes.
So I tried that:
var timesheetSum = (from ts in db.Timesheets
where (ts.EmployeeId == employeeId)
select new
{
hoursOfWork = DbFunctions.DiffMinutes(ts.BeginOfWork, ts.EndOfWork) / 60
}).Sum(ts => ts.hoursOfWork);
But here, hoursOfWork seems to be rounded (integer), so 2,5 hours will result in 2. Perhaps a conversion of the result would work but I don't get it run.
`(double)hoursOfWork` results in an error.
Perhaps someone has a link to a complete guide, how to convert SQL to Linq-queries.
SOLUTION
var timesheetSum = (from ts in db.Timesheets
where (ts.EmployeeId == employeeId && ts.TimesheetDate <= DateTime.Today)
select new
{
hoursOfWork = DbFunctions.DiffMinutes(ts.BeginOfWork, ts.EndOfWork)/60m
}).Sum(ts => ts.hoursOfWork);
decimal result = 0;
if(timesheetSum!=null)
result = (decimal)timesheetSum;
Thanks a lot
Carsten

ESPER: 'Partition by' CLAUSE ERROR

The issue that I have is using the clause 'partition by' in 'Match Recognize', the 'partition by' clause seems to support just 99 different events because when I have 100 or more different events it does not group correctly. to test this I have the following EPL query:
select * from TemperatureSensorEvent
match_recognize (
partition by id
measures A.id as a_id, A.temperature as a_temperature
pattern (A)
define
A as prev(A.id) is null
)
I am using this query basically to get the first event (first temperature) of each device, however testing with 10, 20, 50, ... 99 different devices it works fine but when I have more than 99, it seems that ESPER resets all the events send before the device with id=100, and if I send a event that is of the device with id=001, ESPER takes it as if it was the first event.
it seems that 'partition by' just supports 99 different events and if you add one more the EPL is reset or something like that. Is it a restriction that 'partition by' clause has?, how I can increase this threshold because I have more than 100 devices?.
ESPER version: 5.1.0
Thanks in advance
Demo Class:
public class EsperDemo
{
public static void main(String[] args)
{
Configuration config = new Configuration();
config.addEventType("TemperatureSensorEvent", TemperatureSensorEvent.class.getName());
EPServiceProvider esperProvider = EPServiceProviderManager.getProvider("EsperDemoEngine", config);
EPAdministrator administrator = esperProvider.getEPAdministrator();
EPRuntime esperRuntime = esperProvider.getEPRuntime();
// query to get the first event of each temperature sensor
String query = "select * from TemperatureSensorEvent "
+ "match_recognize ( "
+ " partition by id "
+ " measures A.id as a_id, A.temperature as a_temperature "
+ " after match skip to next row "
+ " pattern (A) "
+ " define "
+ " A as prev(A.id) is null "
+ ")";
TemperatureSubscriber temperatureSubscriber = new TemperatureSubscriber();
EPStatement cepStatement = administrator.createEPL(query);
cepStatement.setSubscriber(temperatureSubscriber);
TemperatureSensorEvent temperature;
Random random = new Random();
int sensorsQuantity = 100; // it works fine until 99 sensors
for (int i = 1; i <= sensorsQuantity; i++) {
temperature = new TemperatureSensorEvent(i, random.nextInt(20));
System.out.println("Sending temperature: " + temperature.toString());
esperRuntime.sendEvent(temperature);
}
temperature = new TemperatureSensorEvent(1, 64);
System.out.println("Sending temperature: sensor with id=1 again: " + temperature.toString());
esperRuntime.sendEvent(temperature);
}
}

What to use - While vs Cursor to improve performance of procedure in sybase

I am trying to improve the performance of stored procedure which is currently taking more than 5 hours..
I have done below things to improve performance of this procedure-
-- i have created indexes for each table.
--Instead of count(*), i am using count(1).
But i am just wondering what to use in place of while loop, if possible, Can i use cursor? will there be any impact because i have read cursors do take a lot of time in processing..
Summary of procedure:
- Calculating row count of a table.
- for every row count selecting paramters.
- These parameters are being used by another procedure for the execution.
DECLARE #lnTotalCount INT
SELECT #lnTotalCount = COUNT(*) FROM
firstTable chksts
SELECT #lnRecordCount = 1, #lnRowsProcessed =0
WHILE #lnRecordCount <= #lnTotalCount
BEGIN
-- SET ROWCOUNT 1
SELECT #lcCKPY_REF_ID = ckck.CKPY_REF_ID,
#lnCKCK_SEQ_NO = ckck.CKCK_SEQ_NO,
#lcPYPY_ID = ckck.PYPY_ID,
#lnCKCK_CK_NO = ckck.CKCK_CK_NO,
#ldtCKCK_CASHED_DT = ckck.CKCK_CASHED_DT,
#ldtCKCK_PRINTED_DT = ckck.CKCK_PRINTED_DT,
#ldtCKCK_REISS_DT = ckck.CKCK_REISS_DT,
#lcCKCK_TYPE = ckck.CKCK_TYPE,
#lcCKCK_PAYEE_NAME = ckck.CKCK_PAYEE_NAME,
#lcCKCK_CURR_STS = LTRIM(RTRIM(chksts.[TRANSACTION])),
#lnCKST_SEQ_NO = ckck.CKST_SEQ_NO,
#lcCKCK_REISS_USUS_ID = ckck.CKCK_REISS_USUS_ID,
#lnCKCK_LOCK_TOKEN = ckck.CKCK_LOCK_TOKEN,
#ldtATXR_SOURCE_ID = ckck.ATXR_SOURCE_ID,
#lnBPID_CK_NO = chksts.SERIAL_NUMBER
FROM
firstTable chksts,
secondTable ckck,
thirdTable bpid
WHERE ckck.CKPY_REF_ID = bpid.CKPY_REF_ID
AND bpid.BPID_CK_NO = chksts.SERIAL_NUMBER
AND ckck.CKCK_SEQ_NO = bpid.CKCK_SEQ_NO
AND ckck.CKCK_CURR_STS IN ('03','X3')
AND chksts.ID = #lnRecordCount
IF(##ROWCOUNT<>0) /* 1.5 If-Else condition*/
BEGIN
EXEC #lnRetCd = ABProcedure
NULL,
NULL,
#lcCKPY_REF_ID,
#lnCKCK_SEQ_NO,
#lcPYPY_ID,
#lnCKCK_CK_NO,
#ldtCKCK_CASHED_DT,
#ldtCKCK_PRINTED_DT,
#ldtCKCK_REISS_DT,
#lcCKCK_TYPE,
#lcCKCK_PAYEE_NAME,
#lcCKCK_CURR_STS,
#lnCKST_SEQ_NO,
#lcCKCK_REISS_USUS_ID,
#lnCKCK_LOCK_TOKEN,
#ldtATXR_SOURCE_ID
SELECT #lnRowsProcessed = #lnRowsProcessed + ##ROWCOUNT
SELECT #lnRecordCount = #lnRecordCount + 1

Linq - Limit number of results by same value of a field

I have a problem with a creation of a Linq to Entities (Oracle 11g) request. Here is the
I have a table TREATMENT with three column (simplified version) : ID, STATE and APPLICATION. Here is a sample :
ID STATE APPLICATION
1 A MAJ
2 A FLUX
3 A FLUX
4 R REF
5 A REF
Now, my objectives are to retrieve the data with theses rules:
State must be A (added)
Number of rows per application below a max value
The max value is minored b the number of row with State = R (per application)
Exemple : If the max value is 1, I must retrieve row 1 and 2. (Can't retrieve row 5 since there is already a REF with state R (the row 4))
I manage to retrieve all the row when the number of R is equal or greater than the max value, but I don't see how to limit my number of result in order to respect the max value.
Here is the request :
using (Entities bdd = new Entities())
{
var treatments = from trt in bdd.TREATMENT
let app = from t in bdd.TREATMENT
where t.STATE == "R"
group t by t.APPLICATION into grouped
where grouped.Count() >= maxPerApplication
select grouped.Key
where trt.STATE == "A" && !app.Contains(trt.APPLICATION)
orderby trt.ID
select new TreatmentDto()
{
Id = trt.ID
};
result = treatments.ToList();
}
In SQL, I would use an inner request and a ROWNUM to limit the number of result, but I don't see how to do it. The only solution I see is to do the request in two parts, but I want to avoid this to maintain the consistency of the information.
I found a solution, not sure if it's the best, but it works :
using (Entities bdd = new Entities())
{
from trt in bdd.TREATMENT
where trt.STATE == "A" &&
(from trt2 in bdd.TREATMENT
where trt2.STATE == "A" && trt2.APPLICATION == trt.APPLICATION && trt2.ID <= trt.ID
select trt2).Count() <= maxPerApplication - (from appp in bdd.TREATMENT
where appp.STATE == "R"
&& appp.APPLICATION.Equals(trt.APPLICATION)
select appp).Count()
select new TreatmentDto()
{
Id = trt.ID
};
result = treatments.ToList();
}