Subsonic: The member 'Days' is not supported - subsonic

I am using Subsonic (SimpleRepository) to query my SQL 2008 database. I am trying to write a query that will calculate the number of days between two fields and return records where the difference is less than a given number. However, I get a "The member 'Days' is not supported" error.
Can anybody suggest an alternative query?
Here's the query I'm trying to run:
var repository = new SimpleRepository("MyConnection",
SimpleRepositoryOptions.None);
var query = (from c in repository.All<Data.Customer>()
where c.LastSynchronizedOn == null ||
(c.LastSynchronizedOn - c.CreatedOn).Days <= 7)
select c).Distinct();
EDIT:
I tried:
(c.LastSynchronizedOn == null || (c.LastSynchronizedOn.Value - c.CreatedOn).Days <= 7)
I get the same exception: The member 'Days' is not supported
I also tried:
(c.LastSynchronizedOn == null || ((c.LastSynchronizedOn - c.CreatedOn) > new TimeSpan(7, 0, 0, 0)))
I get: Failed to convert parameter value from a TimeSpan to a String.

Please check the data type of fields LastSynchronizedOn and CreatedOn as the problem is not related to SubSonic but .Net is complaining (if this is right way to put it) because the expression (c.LastSynchronizedOn - c.CreatedOn) might not be returning DateTime object.
EDIT:- as per your comment please try this
(c.LastSynchronizedOn.Value - c.CreatedOn).Days
EDIT (2): the statement
(c.LastSynchronizedOn == null ||
((c.LastSynchronizedOn - c.CreatedOn) > new TimeSpan(7, 0, 0, 0)))
returns boolean (true or false)
try this:
var repository = new SimpleRepository("MyConnection",
SimpleRepositoryOptions.None);
var query = (from c in repository.All<Data.Customer>()
where ((c.LastSynchronizedOn ??
new DateTime(c.CreatedOn.Year, c.CreatedOn.Month,
c.CreatedOn.Day).AddDays(-7))
- c.CreatedOn).Days <= 7) select c).Distinct();

Related

How to use correctly IN filter in Acumatica Report Designer?

A bit new in Acumatica, I've been tasked to update a report which it in on itself is pretty easy, just adding a new value to a filter.
The part of the query I'm modifying is:
( [INRegister].[TransferType] = '1' AND [INTran].[TranDate] BETWEEN CONVERT(DATETIME, '20220101 0:0:0.000') AND CONVERT(DATETIME, '20230112 0:0:0.000') AND ( [INRegister].[DocType] = 'I' OR [INRegister].[DocType] = 'A') AND ( [INTran].[ReasonCode] = 'Null' OR [INTran].[ReasonCode] = 'BAJACADUCA' OR [INTran].[ReasonCode] = 'INISSUED' OR [INTran].[ReasonCode] = 'Null') AND ( [InventoryItem].[PreferredVendorID] = NULL OR NULL IS NULL ))
ORDER BY [InventoryItem].[ItemClassID], [InventoryItem].[PreferredVendorID], [INTran].[TranDate] OPTION(OPTIMIZE FOR UNKNOWN)
I need to use In when ReasonCode is INISSUED because it should have another value (BAJAMERCADERIA) too but everytime I try to use the In filter the second value is ignored or truncated when I check the trace.
The second value is primarily used for the between clause. Have you tried a comma delimited list in value1? i.e. BAJAMERCADERIA,INISSUED

How to check if ArangoDB query is not empty?

I would like to make an exists PostgreSQL query.
Let's say I have a Q ArangoDB query (AQL). How can I check if Q returns any result?
Example:
Q = "For u in users FILTER 'x#example.com' = u.email"
What is the best way to do it (most performant)?
I have ideas, but couldn't find an easy way to measure the performance:
Idea 1: using Length:
RETURN LENGTH(%Q RETURN 1) > 0
Idea 2: using Frist:
RETURN First(%Q RETURN 1) != null
Above, %Q is a substitution for the query defined at the beginning.
I think the best way to achieve this for a generic selection query with a structure like
Q = "For u in users FILTER 'x#example.com' = u.email"
is to first add a LIMIT clause to the query, and only make it return a constant value (in contrast to the full document).
For example, the following query returns a single match if there is such document or an empty array if there is no match:
FOR u IN users FILTER 'x#example.com' == u.email LIMIT 1 RETURN 1
(please note that I also changed the operator from = to == because otherwise the query won't parse).
Please note that this query may benefit a lot from creating an index on the search attribute, i.e. email. Without the index the query will do a full collection scan and stop at the first match, whereas with the index it will just read at most a single index entry.
Finally, to answer your question, the template for the EXISTS-like query will then become
LENGTH(%Q LIMIT 1 RETURN 1)
or fleshed out via the example query:
LENGTH(FOR u IN users FILTER 'x#example.com' == u.email LIMIT 1 RETURN 1)
LENGTH(...) will return the number of matches, which in this case will either be 0 or 1. And it can also be used in filter conditions like as follows
FOR ....
FILTER LENGTH(...)
RETURN ...
because LENGTH(...) will be either 0 or 1, which in context of a FILTER condition will evaluate to either false or true.
Do you need and AQL solution?
Only the count:
var q = "For u in users FILTER 'x#example.com' = u.email";
var res = db._createStatement({query: q, count: true}).execute();
var ct = res.count();
Is the fastest I can think of.

Couch DB returns empty array when passing date in multiple keys using startkey and end key

My Query is:
SELECT SUM(hrs) from Work WHERE EmployeeNumber =? AND EmployeeName=? AND WorkDate BETWEEN ? AND ?
My KEY for couch DB
when I pass the other two strings like employee number and name I am getting data but when am adding date also I get empty array, but I see there is data for these dates.
I have tried sending dates as strings also but no result.
?startkey=["91444","Rick",[2018,2,4]]&endkey = ["91444","Rick",[2018,2,15]]
As posted in your comment, your view functions look like this:
map: "function (doc) {
if (doc.EmployeeNumber && doc.EmployeeName && doc.workDate) {
var date = doc.workDate.split('-');
var year = date[0];
var mon = date[1]; if(mon.charAt( 0 ) == '0') { mon = mon.slice( 1 ); }
var day = date[2]; if(day.charAt( 0 ) == '0') { day = day.slice( 1 ); }
emit(doc.EmployeeNumber,doc.EmployeeName,[Number(year), Number(mon), Number(day)], doc.hrs);
}
}",
reduce: "_sum"
In your map function you are emitting 4 things:
emit(
doc.EmployeeNumber,
doc.EmployeeName,
[Number(year), Number(mon), Number(day)],
doc.hrs
);
As mentioned in this documentation
The emit() function always takes two arguments: the first is key, and the second is value.
Therefore your map function doesn't look right.

mutivalue date field search not working

I have a multivalue field called freeDaysPool which has multiple dates as strings. With the following code, the search does not return anything. If I leave that field out, the search works just fine with the two other fields. I read that I should use CONTAINS with multivalue fields but then I got query not understandable.
I've tried the back-end field as a date field and as a text field and tested all kinds of query combinations and date formats but no luck. Any help is really appreciated.
This is the search button code:
var query = new Array("");
var cTerms = 0;
// Field 1
var search01 = getComponent("searchcustomReservationField01").getValue();
if (#Contains(#Text(search01),"any city")){"";}
else {query[cTerms++] = '[customReservationField01]="' + search01 +'"'};
// Field 2
var search02 = getComponent("searchcustomReservationField02").getValue();
if (#Contains(#Text(search02),"any city")){"";}
else {query[cTerms++] = '[customReservationField02]="' + search02 + '"'};
// Date 1
var formatter = new java.text.SimpleDateFormat("d.M.yyyy");
query[cTerms++] = 'FIELD freeDaysPool = ' + formatter.format(getComponent("searchcustomDateField01").getValue());
// if query is still empty, we fill it with asterisk
if(query == "" || query == null){
query[cTerms++] = "*";
}
// make all as string
qstring = query.join(" AND ").trim();
sessionScope.searchString = qstring;
It will return query as:
[customReservationField01]="Oslo" AND [customReservationField02]="Oslo" AND FIELD freeDaysPool = 6.2.2015
AFAIK date values in formulas (and a query is a formula) have to be noted like
[06.02.2015]
to compare them. Just try to use your formular in the Notes Client to do a fulltext search. If you get results and no errors you found the correct format. That's at least the way I test queries as I'm not able to remind the syntax for years :-D
Thank you for all the help! Seems that Domino keeps the field type as date field even if you change it back to text field (noticed that from the notes FTsearch). I created completely new text field and added the days as strings in dd.MM.yyyy format. I also search them as strings and it works fine.
The changed code bit now looks like this:
// Date 1
var formatter = new java.text.SimpleDateFormat("dd.MM.yyyy");
query[cTerms++] = '[freeDays] CONTAINS "' + formatter.format(getComponent("searchcustomDateField01").getValue())+'"';

Speeding up SQL Query with CASE in JOIN

working on a DB2 database using SQL in VBA to make some custom reports. I came up with the below query, but it took like 45-minutes to run with 80,000 results... the table BILLPRC probably has twice that in total before the WHERE clause. Just wondering if there is a better way to write the query to speed it up. This might be a pretty ambiguous question, so I can explain further if you need more info.
SELECT b.BLCO# || RIGHT('00000' || b.BLACCT, 5) Acct, b.BLRECT Type, b.BLREC# Record, i.INAME || ' ' || i.INAME2 Desc, b.BLPPGM# Promo, SUBSTR(b.BLPEFFD, 4, 2) || SUBSTR(b.BLPEFFD, 6, 2) || SUBSTR(b.BLPEFFD, 2, 2) Eff, SUBSTR(b.BLPENDD, 4, 2) || SUBSTR(b.BLPENDD, 6, 2) || SUBSTR(b.BLPENDD, 2, 2) Exp, CASE
WHEN (p.PPPRC1 = '0') THEN (p.PPPRC2)
WHEN (p.PPPRC1 != '0') THEN (p.PPPRC1) END Price,
CASE
WHEN (p.PPPRC1 = '0') THEN (p.PPCST2)
WHEN (p.PPPRC1 != '0') THEN (p.PPCST1) END Allow, i.ILASTC Cost
FROM QS36F.BILLPRC b
LEFT JOIN QS36F.PROMO p
ON b.BLREC# || b.BLPPGM# = p.PPREC || p.PPPGM#
LEFT JOIN QS36F.ITEM i
ON CASE
WHEN (b.BLRECT = 'I') AND (b.BLREC# = i.IMFGR || i.ICOLOR || i.IPATT) THEN 1
WHEN (b.BLRECT = 'P') AND (b.BLREC# = i.IPRCCD) THEN 1
END = 1
WHERE (b.BLPPGM# != '') AND (b.BLSTS != 'H')
ORDER BY (b.BLACCT)
I have a feeling there isn't given the amount of records and CASEs being checked.
You may likely get better performance by changing your WHERE predicate (b.BLPPGM# != '') AND (b.BLSTS != 'H') by rewriting it in the join condition(s).
Try not to concatenate your fields used for joining, if possible. For example, instead of
LEFT JOIN QS36F.PROMO p
ON b.BLREC# || b.BLPPGM# = p.PPREC || p.PPPGM#
you could say
LEFT JOIN QS36F.PROMO p
ON b.BLREC# = p.PPREC
and b.BLPPGM# = p.PPPGM#
or equivalently
LEFT JOIN QS36F.PROMO p
ON (b.BLREC#, b.BLPPGM#) = (p.PPREC, p.PPPGM#)
adding in the logic from your WHERE clause
LEFT JOIN QS36F.PROMO p
ON (b.BLREC#, b.BLPPGM#) = (p.PPREC, p.PPPGM#)
Of course, this assumes that the corresponding fields are the same type, or compatible types, and ideally the fields will be the same size. DB2 can often automatically convert one type to another compatible type. String types are often compatible with each other, and numeric types often with each other.
Then, most importantly, make sure you have the right indexes available. (I'm not too familiar with the S/36 mode environment, but I'm assuming you can create indexes over it.) Indexes can also be built over a derived column, ie. an expression such as concatenation.
For reporting purposes, use a materialized query table, unless if you can't really afford the CPU time. I know it's a bit lazy, but MQTs are meant for when you are okay with getting for instance hourly updated results, and don't want to start normalizing and optimizing your database. You have a working logic, and you apparently understand it, so go with it.
This looks like it's DB2 for i....you might want to tag it appropriately
Assuming it is, have you used the "Run & Explain" option in iNav's Run SQL scripts to see if the DB recommends any new indexes?

Resources