Is there an OR clause in LINQ? - linq

I am trying to query an XML document for the specific records that I need. I know that the line containing the "or where" case below is incorrect, but I'm hoping it will illustrate what I am trying to accomplish. Can you do a conditional where clause on two seperate properties?
XDocument xd = XDocument.Load("CardData.xml");
SearchList.ItemsSource = from x in xd.Descendants("card")
where x.Element("title").Value.ToUpper().Contains(searchterm.ToUpper())
or where x.Element("id").Value.Contains(searchterm)
select new Card
{
Title = x.Element("title").Value
};

Yes - simply use the boolean or || and combine your conditions into one Where clause:
where x.Element("title").Value.ToUpper().Contains(searchterm.ToUpper()) ||
x.Element("id").Value.Contains(searchterm)
Also note just as a minor optimization, I would pre-compute some of the operations you currently have in your Where clause so they are not performed on every item in the list - probably doesn't matter but it might when you have a lot of elements (and is just a good habit to get into in my opinion):
string searchTermUpperCase = searchterm.ToUpper();
SearchList.ItemsSource = from x in xd.Descendants("card")
where x.Element("title").Value.ToUpper().Contains(searchTermUpperCase)
or where x.Element("id").Value.Contains(searchterm)
..

Related

Linq query increase performance efficient query

int mappedCount = (from product in products
from productMapping in DbContext.ProductCategoryMappings
.Where(x => product.TenantId == x.TenantId.ToString() &&
x.ProductId.ToString().ToUpper() == product.ProductGuid.ToUpper())
join tenantCustMapping in DbContext.TenantCustCategories
on productMapping.Value equals tenantCustMapping.Id
select 1).ToList().Sum();
I need to increase the performance.
When mapping product two tables each item having multiple product
If you want to increase performance, you'd need to know the volumes of data that are getting sent around. How many "products" are in your variable.
It may be quicker to update your products list to contain integers / guids and send that to your database rather than send strings that the database has to run ToUpper() on before comparing them.
something like:
var convertedList = products.Select( new {TenantId = int.parse(product.TenantId), productId = Guid.Parse(x.ProductId)}
Then sending that to your Db, and comparing them directly
I think changing "Select 1).ToList().Sum()" to ".Count()" will improve performance. Even if not, it'll help readability.

Oracle 9i Sub query

Hi Can any one help me out of this query forming logic
SELECT C.CPPID, c.CPP_AMT_MANUAL
FROM CPP_PRCNT CC,CPP_VIEW c
WHERE
CC.CPPYR IN (
SELECT C.YEAR FROM CPP_VIEW_VIEW C WHERE UPPER(C.CPPNO) = UPPER('123')
AND C.CPP_CODE ='CPP000000000053'
and TO_CHAR(c.CPP_DATE,'YYYY/Mon')='2012/Nov'
)
AND UPPER(C.CPPNO) = UPPER('123')
AND C.CPP_CODE ='CPP000000000053'
and TO_CHAR(c.CPP_DATE,'YYYY/Mon') = '2012/Nov';
Please Correct me if i formed wrong query structure, in terms of query Performance and Standards. Thanks in Advance
If you have some indexes or partitioned tables I would not use functions on columns but on variables, to be able to use indexes/select partitions.
Also I use ANSI 92 SQL syntax. You don't specify(or not directly) a join contition between cpp_prcnt and cpp_view so it is actually a cartesian product(cross join)
SELECT C.CPPID, c.CPP_AMT_MANUAL
FROM CPP_PRCNT CC
CROSS JOIN CPP_VIEW c
WHERE
CC.CPPYR IN (
SELECT C.YEAR
FROM CPP_VIEW_VIEW C
WHERE C.CPPNO = '123'
AND C.CPP_CODE ='CPP000000000053'
AND trunc(c.CPP_DATE,'MM')=to_date('2012/Nov','YYYY/Mon')
)
AND C.CPPNO = '123'
AND C.CPP_CODE ='CPP000000000053'
AND trunc(c.CPP_DATE,'MM')=to_date('2012/Nov','YYYY/Mon')
If you show us the definition of cpp_view_view(seems to be a view over cpp_view), the definition(if simple) of CPP_VIEW and what you're trying to achieve, I bet there are more things to be improved/fixed.
There are a couple of things you could improve:
if possible, get rid of the UPPER() in the comparison - this will render any indices useless. If that's not possible, consider a function-based index on UPPER(CPPNO)
do not convert your DATE column to a string to compare it with a string - do it the other way round (i.e. convert your string to a date => only one conversion needed instead of one per table row, use of indices possible)
play around with EXISTS instead of IN, as suggested by Dileep - might be faster

set filter to - INLIST - Visual Foxpro 7

I am working on some legacy code, and I have the following wonderful issue. I am hoping some FoxPro experts can help!
The infrastructure of this legacy system is setup so that I have to use the built-in expression engine to return a result set, so no go on the SQL (i know that would be so much easier!)
Here is the issue.
I need to be able to do something like
PUBLIC ARRAY(20) ArrayOfValuesToFilterBy
SELECT dataTable
SET FILTER TO logicalField = .T. and otherField NOT INLIST(ArrayOfValuesToFilterBy)
However, I know this wont work, I just need the equivalency...not using SQL.
I can generate the list of values to filter by via SQL, just not the final record select due to the legacy infrastructure constraint.
Thanks!
First, a logical field you do not have to do explicit
set filter to Logicalfield = .t.
you can just do
set filter to LogicalField
or
set filter to NOT LogicalField
Next, on the array. VFP has a function ASCAN() which will scan an array for a value, if found, will return the row number within the array that matches what you are looking for.
As for arrays... ex:
DIMENSION MyArray[3]
MyArray[1] = "test1"
MyArray[2] = "something"
MyArray[3] = "anything else"
? ASCAN( MyArray, "else" ) && this will return 0
? ASCAN( MyArray, "anything else" ) && this will return 3
If you are doing a "set filter", the array needs to be "in scope" for the duration of the filter. If you set filter in a procedure the array exists, leave the procedure and the array is gone, you're done.
So, you could do
set filter to LogicalField and ASCAN( YourArray, StringColumnFromTable ) > 0
Now, if you want a subset to WORK WITH, you can do a SQL-Select and pull the data into a CURSOR (temporary read-write table) that has the same capabilities of the original table (except auto-increment when adding)...
I typically name my temporary cursors prefixed with "C_" for "CURSOR OF" so when I'm working with tables, I know if its production data, or just available for temp purposes for quicker display, presentation, extractions from other origins as needed.
use in select( "C_FinalRecords" )
select * from YourTable ;
where LogicalField ;
and ASCAN( YourArray, StringColumnFromTable ) > 0;
into cursor C_FinalRecords READWRITE
Then, you can just use that...
select C_FinalRecords
scan
do something with the record, or values of it...
endscan
or.. bind to a grid in a form, etc...
The INLIST() function takes an expression to search for and up to 24 expressions of the same data type to search.
SELECT dataTable
SET FILTER TO logicalField = .T. AND NOT INLIST(otherField, 'Value1', 'Value2', 'Value3', 'Value4')
I am making some assumptions here, that what you want to do is create a filter with a dynamic in list statement ? If this is correct have a play with this example :-
lcList1="ABCD"
lcList2="EFGH"
lcList3="IJKL"
lcList4="MNOP"
lcList5="QRST"
lcFullList=""
lcFullList=lcFullList+"'"+lcList1+"',"
lcFullList=lcFullList+"'"+lcList2+"',"
lcFullList=lcFullList+"'"+lcList3+"',"
lcFullList=lcFullList+"'"+lcList4+"',"
lcFullList=lcFullList+"'"+lcList5+"'"
lcField="PCode"
lcFilter="SET FILTER TO INLIST ("+lcField+","+lcFullList+")"
The results of the above would create the following filter statement and store it in lcFilter
SET FILTER TO INLIST (PCode,'ABCD','EFGH','IJKL','MNOP','QRST')
you can then use macro substitution
Select dataTable
&lcFilter
Bear in mind that there is likely to be some limitations on how many items you can define in a INLIST() statement

data structure algorithms for database searching

I was used to the traditional way of doing database searching with the following
using wildcards for term searches
using where clause for specific data like addresses and names
but at other times, I found these common methods to produce code that is so bloated, especially when it comes to complex searches.
Are there algorithms out there that you use for complex database searching? I tried to look for some but had a hard time doing so. I stumbled accross the binary search but I can't find a use for it :(
EDIT: Here's a pseudocode of a search I was working on. It uses jquery range sliders for maximum and minimum searching
query = 'select * from table'
if set minprice and not set maxprice
if minprice = 'nomin'
query += ' where price < maxprice'
else
query += ' where price < maxprice and price < minprice'
if not set minprice and set maxprice
if maxprice = 'nomax'
query += ' where price > minprice'
else
query += ' where price > minprice and price < maxprice'
if set maxprice and set minprice
if maxprice = 'nomax'
query += ' where price > minprice'
else
query += ' where price > minprice and price < maxprice'
this may not be the codebase by which you base your answers. I'm looking for more elegant ways of doing database searching.
EDIT by elegant I mean ways of rewriting the code to to achieve faster queries at less lines of code
Alright, I'm still not very clear on what you want, but I'll give it a shot...
If you're trying to speed up the query, you don't need to worry about "improved algorithms". Just make sure that any columns that you're searching on (price in your example) have an index on them, and the database will take care of searching efficiently. It's very good at it, I promise.
As for reducing the amount of code, again, I can't speak for every case, but your above pseudocode is bloated because you're handling the exact same case multiple times. My code for something like that would be more like this (pseudocode, no particular language):
if (set(minprice) and minprice != 'nomin')
conditions[] = 'price > minprice'
if (set(maxprice) and maxprice != 'nomax')
conditions[] = 'price < maxprice'
query = 'select * from table'
if (notempty(conditions))
query += ' where '+conditions.join(' and ')
Remeber speed of a query is not just the query itself. Also, greatly depends on how the db is structured. Is this a std relational layout, or a star, or? Are your keys indexed, and do you have secondary indexes? Are you expecting to bring back a lot of data, or just a couple of rows? Are you searching on columns where the db has to do a text search, or on numeric values. And of course, on top of that, how is the db physically layed out? index's and heavy hit tables on seperate drives? and so forth. Like the previous people mentioned, maybe a specific example would be more helpful in trying to solve
When interfacing with a database, you're far better off with a complex and ugly query than with an 'elegant' query which has you duplicating database search functionality inside your application. Each call to the database has a cost associated with it. If you write code to search a database within your application, it's virtually guaranteed to be more expensive.
Unless you are actually writing a database (tall order), let the database do the searching.
try to focus on reorganizing your query building process.
query = select + ' where ' + filter1 + filter2
select = 'select * from table'
filter1 = '';
if set minprice
if minprice = 'nomin'
filter1 = price > minprice'
else
filter1 = 'price < minprice'
and so on ... 'til the building the full query :
query = select;
if any filter on
query += ' where '
first = true
if set filter 1
if not first
query += ' and '
query += filter1
and so on...
you can put your filters in an array. it is more 'scalable' for your code.
The major problem with your code is that it unnecessarily mulls over every possible combination of set(minprice) and set(maxprice), while they can be treated independently:
query = 'select * from table'
conditions = [] #array of strings representing conditions
if set(minprice):
conditions.append("price < minprice")
if set(maxprice):
conditions.append("price > maxprice")
if len(conditions)>0:
query += ' WHERE ' + " and ".join(conditions)
In general it is beneficial to separate generation of conditions (the if set(...) lines above) from building the actual query. This way you don't need a separate if to generate (or skip) an "AND" or "WHERE" before each generated condition but instead you can just process it in one place (the last two lines above) adding the infixes as necessary.

PL/SQL: UPDATE inside CURSOR, but some data is NULL

I'm still learning some of the PL/SQL differences, so this may be an easy question, but... here goes.
I have a cursor which grabs a bunch of records with multiple fields. I then run two separate SELECT statements in a LOOP from the cursor results to grab some distances and calculate those distances. These work perfectly.
When I go to update the table with the new values, my problem is that there are four pieces of specific criteria.
update work
set kilometers = calc_kilo,
kilo_test = test_kilo
where lc = rm.lc
AND ld = rm.ld
AND le = rm.le
AND lf = rm.lf
AND code = rm.code
AND lcode = rm.lcode
and user_id = username;
My problem is that this rarely updating because rm.lf and rm.le have NULL values in the database. How can I combat this, and create the correct update.
If I'm understanding you correctly, you want to match lf with rm.lf, including when they're both null? If that's what you want, then this will do it:
...
AND (lf = rm.lf
OR (lf IS NULL AND rm.lf IS NULL)
)
...
It's comparing the values of lf and rm.lf, which will return false if either is null, so the OR condition returns true if they're both null.
I have a cursor which grabs a bunch of records with multiple fields. I then run two separate SELECT statements in a LOOP from the cursor results to grab some distances and calculate those distances. These work perfectly.
When I go to update the table with the new values, my problem is that there are four pieces of specific criteria.
The first thing I'd look at is not using a cursor to read data, then make calculations, then perform updates. In 99% of cases it's faster and easier to just run updates that do all of this in a single step
update work
set kilometers = calc_kilo,
kilo_test = test_kilo
where lc = rm.lc
AND ld = rm.ld
AND NVL(le,'x') = NVL(rm.le,'x')
AND NVL(lf,'x') = NVL(rm.lf,'x')
AND code = rm.code
AND lcode = rm.lcode
and user_id = username;

Resources