I am using LINQ to SQL to retrieve data, using boolean conditions (BIT columns in SQL). My LINQ query looks something like this:
var query = from r in db.Requests
select r;
query = query.Where(r => r.Completed == someBooleanVal);
query = query.Where(r => r.Cancelled == someOtherBool);
return query.ToList();
The 'Where()' gets applied in a different method, that's why I'm putting it in separately.
When the boolean values are given as false, the generated SQL looks something like this:
SELECT [t0].[col1], [t0].[col2], [t0].[col3], [t0].[etc]
FROM [dbo].[Requests] AS [t0]
WHERE (NOT(([t0].[Cancelled]) = 1) AND (NOT(([t0].[Completed]) = 1)
in stead of what I would use:
WHERE [t0].[Cancelled] = 0 AND [t0].[Completed] = 0
This runs very, very slowly. I strongly suspect that it is because of the negative conditions on the boolean values it generated (all the selected columns are covered by an index, and the two columns in the where clause have a separate index on them).
Why is it generating negative conditions? How can I fix it?
var query =
from r in db.Requests.Where(r => r.Completed == someBooleanVal && r.Cancelled == someOtherBool)
select r;
return query.ToList();
Hope it can help you and have a nice day.
Related
I want to select a bunch distinct records based off a composite key. In SQL I'd write something like this:
SELECT * FROM security WHERE (
exchange_code = 'exchange_code_1' AND code = 'code_1')
OR (exchange_code = 'exchange_code_2' AND code = 'code_2')
...
OR (exchange_code = 'exchange_code_N' AND code = 'code_N')
)
With SQLAlchemy I'd like to use the filter clause like:
query = sess.query(Security)
[query.filter(
and_(Security.exchange_code == security.exchange_code,
Security.code == security.code)
) for security in securities]
result = query.all()
The problem is filter and where join clauses with an AND not an OR... is there some way to use filter with OR?
Or is my only choice to generate a bunch of individual select's and UNION them? Something like:
first = exchanges.pop()
query = reduce(lambda query, exchange: query.union(exchange.pk_query),
first.pk_query())
query.all()
Use or_:
query = sess.query(Security).filter(
or_(*(and_(Security.exchange_code == security.exchange_code,
Security.code == security.code)
for security in securities)))
If your database supports it, you should use tuple_ instead.
I was told that I could check whether a SELECT statement finds a column with the syntax
$rows = query( "SELECT * FROM tbl WHERE id = idx");
if ( $rows == false )
and it seems to work.
Anyway, if I check if ( $rows == 0 ) it doesn't return the same value.
Shouldn't 0 and false be the same (apart from the type, of course)?
What's the actual value returned by the query when it finds no row? I ask because it doesn't seems to be false, since the statement var_dump( $rows === false ) prints false..
***EDIT: I'm sorry guys, query() was a function from a library someone else wrote and I had no idea (i'm starting now with sql...). It simply excutes an SQL statement, returning an array of all rows in result set or false on (non-fatal) error (like row not found).
I have still a little question, though.
The function returns false when it finds no row, so shouldn't I be able to catch that with if ( $rows === false )?
Why var_dump(false) doens't print me out anything, while var_dump(true) prints me out 1?
I'm not pretty sure if you use simple mysql_* functions, MySQLi or PDO but in any case $rows is not returning the number of resulting rows. It is a boolean value / object returned / created depending of success of your query.
$sql = $mysqli->query("SELECT * FROM tbl WHERE id='1'");
if(!$sql->error)
$number_of_rows = $sql->num_rows; // for sure it will output 1
LINQ gurus, I am looking for help to write a query...
I have a table with Person records, and it has a nullable ParentID column, so it is kind of self-referencing, where each record might have a Parent.
I am looking for unprocessed rows whose parent rows were processed.
This SQL works fine:
SELECT *
FROM Person
where IsProcessed = 0 and
ParentId in
(
select Id from Person
where IsProcessed = 1
)
I tried a number of LINQ queries, but they failed. Now, I'm trying:
var qParent =
from parent in db.Person
where
parent.IsProcessed == true
select parent.ID;
var qChildren = from child in db.Person
where
child.IsProcessed == false
&& child.ParentId.HasValue
select child.ParentId.Value;
var q2 = qChildren.Intersect(qParent);
This yields SQL with a DISTINCT clause, for some reason, and I am baffled why DISTINCT is generated.
My main question is how to write LINQ for the SQL statement above?
Thanks in advance.
Intersect is a set operation - it is meant to return a set of distinct elements from the intersection. It seems reasonable to me that it would use DISTINCT in the SQL. There could be multiple children with the same parent, for example - Intersect should only return that ID once.
Is there any reason you don't want to use a join here?
var query = from parent in db.Person
where parent.IsProcessed
join child in db.Person.Where(child => !child.IsProcessed)
on parent.ID equals child.ParentId.Value
select child;
The query can be translated literally into :
var parentIds = db.Person.Where(x => x.IsProcessed)
.Select(x => x.Id)
.ToList();
var result = db.Person.Where(x => !x.IsProcessed && parentIds.Contains(x => x.Id))
.ToList();
I have a pretty complex linq statement I need to access for different methods. Each of these methods may need to see the resulting data with different parameters. For one method it may be a project code, for another it may be language. The statement is pretty much the same it's just the where part which changes.
I have not been able to figure out how to use different where statements without duplicating the entire linq statement, and that just isn't dry enough for me.
For example (greatly simplified):
var r = from c in customer
where c.name == "some name"
// or it may be
var r = from c in customer
where c.customerId == 8
Is there a way to have both of these in the same statement so I can use one or the other based on what I am doing? I tried an if statement to use one of the where statements or the other, and that didn't go over very well.
You can do it like this:
var r = from c in customer
select c;
if (CustomerName != null)
r = r.Where(c => c.name == CustomerName);
if (CustomerID != null)
r = r.Where(c => c.customerId == CustomerID);
You could make these else if if only one should apply, in my example any criteria that wasn't null would be applied to the query to filter on.
what about something like this?
var useIdForFiltering = false;
var r = from c in customer
where (useIdForFiltering && c.customerId == 8) || (c.name == "some name")
You can pass in a Func delegate to your function (the Where clause takes a Func delegate with a boolean return type). Then use this delegate in the Where clause.
I have 2 tables
1. Client
2. Operations
Operations can result in: Credits or Debits ('C' or 'D' in a char field) along with date and ammount fields.
I must calculate the balance for each client's account using linQ... The result should also show balance 0 for clients whom didn't make operations yet
I have the following function with linQ statement, but I know it could be done in a better and quicker, shorter way, right? Which will be?
public static double getBalance(ref ClasesDeDatosDataContext xDC, string SSN,
int xidClient)
{
var cDebits =
from ops in xDC.Operations
where (ops.idClient == xidClient) && (ops.OperationCode == 'D')
select ops.Ammount;
var cCredits =
from ops in xDC.Operations
where (ops.idClient == xidClient) && (ops.OperationCode == 'C')
select ops.Ammount;
return (double)(cCredits.Sum() - cDebits.Sum());
}
Thanks !!!
I don't know if the LINQ-to-SQL engine can handle the expression, but something like this should be possible:
return (
from ops in xDC.Operations
where ops.idClient == xidClient
select ops.operationCode == 'C' ? ops.Amount : -ops.Amount
).Sum(a => a);
Or perhaps:
return (
from ops in xDC.Operations
where ops.idClient == xidClient
select new { Sign = ops.operationCode == 'C' ? 1.0 : -1.0, Amount = ops.Amount }
).Sum(o => o.Sign * o.Amount);
If the collection is empty, the Sum method returns zero, so that takes care of clients without transactions.
Edit:
Corrected spelling in query: Ampont -> Amount