VB.NET LINQ query Where with AndAlso and Or - vb.net

In VB.NET, if I am doing a LINQ query that looks like this:
From a in entitity.name
Where a.id = id _
AndAlso a.date < currentDate _
AndAlso a.statusId = 1 Or a.statusId = 3
Select
On line 4, will the or clause evaluate to return all entities with a statusId of 3, or will it only return the entities that fit the other criteria and have a statusId of 1 or 3?
If that line were changed to
AndAlso (a.statusId = 1 Or a.statusId = 3)
How would that change the expected results?

In VB.NET, conjunction (And, AndAlso) operators occur before inclusive disjunction (Or, OrElse) operators. See Operator Precedence in Visual Basic.
So as soon as a.statusId = 3 is true, it will return true.
And adding parenthesis
AndAlso (a.statusId = 1 Or a.statusId = 3)
will therefore change the behaviour
from:
return TRUE if (a.id = id AND a.date < currentDate AND a.statusId = 1) OR a.statusId = 3
to:
return TRUE if a.id = id AND a.date < currentDate AND (a.statusId = 1 OR a.statusId = 3)

From a in entitity.name
Where a.id = id _
AndAlso a.date < currentDate _
AndAlso a.statusId = 1 Or a.statusId = 3
Select
is equivalent to having (notice the addition of parentheses below):
From a in entitity.name
Where (a.id = id _
AndAlso a.date < currentDate _
AndAlso a.statusId = 1) Or (a.statusId = 3)
Select
Which would return any results where the id matches, the date is less than currentDate, and the status is 1. It will also return ANY results where the statusId is 3.
Whereas having:
From a in entitity.name
Where a.id = id _
AndAlso a.date < currentDate _
AndAlso (a.statusId = 1 Or a.statusId = 3)
Select
Would then return any results where the id matches, the date is less than currentDate, and the status is 1 or 3.
This is the same type of behavior you would see in SQL, or even in general math. 1 + 2 * 3 does not yield the same result as (1 + 2) * 3. It changes the order of operations/the meaning of the statement completely (at least in this case).

Related

Using Linq for select row from DataTableA where id not in DataTableB

I have two dataTables ,and i want select all rows from DataTable1 where id is not in DataTable2.below what i have tried :
Sql = "select *,N°Reçu as NumRecu from V_Sit_J_Vente,V_Bien where V_Sit_J_Vente.Code_bien=V_Bien.Code_bien and date_situation <= '" + dt2 + "' and date_situation >= '" + dt1 + "'"
Dim GlobalDataVente As DataTable = utilitaire.getDataSet(Sql).Tables(0)
Sql = "select * from V_Reserv_Annule"
Dim GlobalDataAnnule As DataTable = utilitaire.getDataSet(Sql).Tables(0)
Dim query = (From order In GlobalDataVente.AsEnumerable() _
Where order!code_projet = tab.Rows(i).Item("code_projet")).ToList
Dim bannedCCList = From c In GlobalDataAnnule.AsEnumerable() _
Where c!type.Equals("Transfert acompte") = False And c!date_annule <= dt2
Dim exceptBanned = From c In query Group Join b In bannedCCList On c.Field(Of String)("N°Reçu") Equals b.Field(Of String)("num_reserv_remplace")
Into j() From x In j.DefaultIfEmpty() Where x Is Nothing Select c
What i want that "exceptBanned " containt all rows of "query" except row exist in "bannedCCList "
Thanks in advance
You can use Contains for this:
Dim query = (From order In GlobalDataVente.AsEnumerable() _
Where order!code_projet = tab.Rows(i).Item("code_projet")).ToList
Dim bannedCCList = From c In GlobalDataAnnule.AsEnumerable() _
Where c.type.Equals("Transfert acompte") = False And c.date_annule <= dt2
Select c.Field(Of String)("num_reserv_remplace")
Dim exceptBanned = From c In query
Where Not bannedCCList.Contains(c.Field(Of String)("N°Reçu"))
Select c
bannedCCList defines a query that produces the Id values you want to exclude; exceptBanned combines query with this list of Ids into a query that only runs once to return the final results. It works this way because bannedCCList is an IEnumerable. It isn't executed when it's defined, only when it's actually used.

peewee orm: Join three tables with foreign keys, counting middle table

I have the following peewee tables/classes (on a postgres DB) and below the dashed line, an example of what I'd like.
Basically I'm a complete newb at DB queries and have no idea how to structure it: I need, given a list of days (like ['2015-01-01', ...]) to obtain the number of Alerts on each day (if there were any) as a count per Service. Hopefully the example below is clear enough.
class Event(BaseModel):
assessment = CharField(max_length = 4096)
day = DateField()
ongoing = BooleanField()
alertType = CharField(null = True)
links = CharField(null = True, max_length = 4096)
newLinks = CharField(null = True, max_length = 4096)
startTime = TimeField()
endTime = TimeField(null = True)
class Service(BaseModel):
svcid = TextField(unique = True)
name = TextField()
class Alert(BaseModel):
alertId = CharField(unique = True, null = True)
alertLink = CharField(unique = True, null = True)
startTime = TimeField()
endTime = TimeField(null = True)
jcaLink = CharField(max_length = 4096, null = True)
description = CharField(max_length = 4096)
relatedNodes = CharField(null = True)
customerName = CharField(null = True)
jcaUrl = CharField(null = True)
deviceName = CharField(null = True)
event = ForeignKeyField(Event, related_name = 'alerts')
service = ForeignKeyField(Service, related_name = 'alerts')
hosted = CharField(default = None, null = True)
------------------------------------------------------------
Example: Event.id 1 has Event.day '2015-01-01'
Event.id 2 has Event.day '2015-01-02'
Service.id 1 has name "A"
Service.id 2 has name "B"
Alert.id 1 has Alert.event.id 1, Alert.service.id 1
Alert.id 2 has Alert.event.id 2, Alert.service.id 2
Alert.id 3 has Alert.event.id 2, Alert.service.id 1
# end of db
If days is ['2015-01-01', '2015-01-02'], output should be like (not resembling, just broken up/organized somewhat like)
Service A
day 2015-01-01
1 alert
day 2015-01-02
1 alert
-----------------
Service B
day 2015-01-01
1 alert
day 2015-01-02
0 alerts
This should do it. I am not sure if your model adds columns like s.id but I imagine it does. Your start_time is a time field so I use the date() method so we are just comparing date parts.
select s.name, date(a.start_time) as alert_date, count(s.name) as alerts
from alert a join service s on a.service_id = s.id
where date(a.start_time) in ('2015-01-01', '2015-01-02')
group by s.name, alert_date
Note that when doing a group by, all fields selected must be used in a group by or aggregate function. There are ways around this but since you need such little data it was not necessary however I am assuming that service.name is unique.
Also, if you want to get alerts by month, year, etc. you can use extract like this:
select s.name, extract(month from a.start_time) as alert_month,
extract(year from a.start_time) as alert_year, count(s.name) as alerts
from alert a join service s on a.service_id = s.id
where extract(year from a.start_time) = 2015
and extract(month from a.start_time) in (11, 12)
group by s.name, alert_month, alert_year

Update a boolean field as criteria using Count inside IF

I have 2 tables called t_task and t_task_details in MS Access
t_task has 3 columns: task_id, task_description, task_status (task_status column is Yes/No column while the rest are Short Text)
t_task_details also has 3 columns: task_id, task_date and done (done is also Yes/No)
Every task is linked to task_details via task_id.
I want update task_status to Yes / True if ALL task_details.done are Yes / True
I have tried this, but unfortunately it's not working:
UPDATE t_task
INNER JOIN t_task_details ON t_task.task_id = t_task_details.id
SET t_task.task_status = IIF(Count(t_task_details.done) = 0, True, False)
WHERE t_task_details.done = False
I think you can use a query like this:
UPDATE t_task
SET t_task.task_status = true
WHERE (SELECT COUNT(*)
FROM t_task_details
WHERE t_task_details.task_id = t_task.id) =
(SELECT COUNT(*)
FROM t_task_details
WHERE t_task_details.task_id = t_task.id
AND t_task_details.done = True)
I don't test it yet.
Note that this will update status of tasks that has no any details, If you want to remove them from update you can add this to the query:
...
AND EXISTS(SELECT 1 FROM t_task_details
WHERE t_task_details.task_id = t_task.id);
UPDATE :
If you want to update status to false for other records, I suggest you to use this query instead:
UPDATE t_task
SET t_task.task_status = IIF(
(SELECT COUNT(*)
FROM t_task_details
WHERE t_task_details.task_id = t_task.id) =
(SELECT COUNT(*)
FROM t_task_details
WHERE t_task_details.task_id = t_task.id
AND t_task_details.done = True), true, false)
WHERE EXISTS(SELECT 1 FROM t_task_details
WHERE t_task_details.task_id = t_task.id);
You can also use DCount and DSum:
UPDATE
t_task
SET
t_task.task_status =
(DCount("*", "t_task_details", "[task_id] = " & t_task.id & "") =
Abs(DSum("[done]","t_task_details", "[task_id] = " & t_task.id & "")))
If key is not numeric:
(DCount("*", "t_task_details", "[task_id] = '" & t_task.id & "'") =
Abs(DSum("[done]","t_task_details", "[task_id] = '" & t_task.id & "'")))

sql to linq in vb.net

I have to convert it to Linq in vb.net. I am new to sql to linq. Guidance welcomed
select CONVERT(VARCHAR(10),a.StartDt,112) datenew,
COUNT(distinct(b.EmployerAccountOid)) companymoved,
COUNT(distinct(c.EmployerAccountOid)) companyfailed,
COUNT(distinct(d.ProductAccountOid)) planmoved,
COUNT(distinct(e.ProductAccountOid)) planfailed
from ebp.MgnCOREDCDataGroupMigrationRun a
left join ebp.MgnCOREDCMigrationRun b
on a.MigrationRunID = b.MigrationRunID
And TypeCd = 1 and a.MigrationStatusCd = 4
left join ebp.MgnCOREDCMigrationRun c
on a.MigrationRunID = c.MigrationRunID
and TypeCd = 1 and a.MigrationStatusCd = 5
left join ebp.MgnCOREDCMigrationRun d
on a.MigrationRunID = d.MigrationRunID
and TypeCd = 2 and a.MigrationStatusCd = 4
left join ebp.MgnCOREDCMigrationRun e
on a.MigrationRunID = e.MigrationRunID
and TypeCd = 2 and a.MigrationStatusCd = 5
group by CONVERT(VARCHAR(10),a.StartDt,112)
I tried to convert it to Linq with fail.
Dim query1= (From migrationgroup In UnitOfWork.DbContext.Set( Of MgnCOREDCDataGroupMigrationRun)()
Group Join migration In UnitOfWork.Set(of MgnCOREDCMigrationRun)() On migrationgroup.MigrationRunID Equals migration.MigrationRunID And migrationgroup.TypeCode = 1 And migrationgroup.MigrationStatusCode=4 _
Into migrationErrorGrp = Group
From mgeg In migrationErrorGrp.DefaultIfEmpty()
Group Join migration1 In UnitOfWork.Set(of MgnCOREDCMigrationRun)() On migration1.MigrationRunID Equals migrationgroup.MigrationRunID And migrationgroup.TypeCode = 1 And migrationgroup.MigrationStatusCode=4 _
Into migrationErrorGrp1 = Group
From mgeg1 In migrationErrorGrp1.DefaultIfEmpty()
Group Join migration2 In UnitOfWork.Set(of MgnCOREDCMigrationRun)() On migration2.MigrationRunID Equals migrationgroup.MigrationRunID And migrationgroup.TypeCode = 2 And migrationgroup.MigrationStatusCode=5 _
Into migrationErrorGrp2 = Group
From mgeg2 In migrationErrorGrp2.DefaultIfEmpty()
Group Join migration3 In UnitOfWork.Set(of MgnCOREDCMigrationRun)() On migration3.MigrationRunID Equals migrationgroup.MigrationRunID And migrationgroup.TypeCode = 2 And migrationgroup.MigrationStatusCode=5 _
Into migrationErrorGrp3 = Group
From mgeg3 In migrationErrorGrp3.DefaultIfEmpty()
Group By CONVERT(VARCHAR(10),migrationgroup.StartDt,112) into g
select New With{CONVERT(VARCHAR(10),migrationgroup.StartDt,112),
Count(distinct(migration.EmployerAccountOid)) ,
Count(distinct(migration1.EmployerAccountOid)),
Count(distinct(migration2.EmployerAccountOid)),
Count(distinct(migration3.EmployerAccountOid))}).ToList()
If IsNothing(query1) Then
Return Nothing
End If
coredcmigrationhistory =
From coredcmigrationrow In query1()
My query is non-queryable. Can anybody guide me where I m goin wrong

SQL Boolean Vars in Where stament

I am making an rdl report and I have three check-boxes that if checked need to alter my WHERE statement. If none are checked the result should only match by date range. If one or more are checked it needs to return the fields that match the variables corresponding string.
WHERE
(EffectiveDate BETWEEN #StartDate AND #EndDate)
AND (((#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR #IncludeSEWPrefix = 0)
AND ((#IncludePAWPrefix = 1 AND PrefixId = 'PAW') OR #IncludePAWPrefix = 0)
AND ((#IncludeRPLPrefix = 1 AND PrefixId = 'RPL') OR #IncludeRPLPrefix = 0))
My code so far works when none are checked and when one is checked, but returns nothing when more than one check-box has been checked. So to try and fix this I altered the code to this
WHERE
(EffectiveDate BETWEEN #StartDate AND #EndDate)
AND ((((#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR #IncludeSEWPrefix = 0)
OR ((#IncludePAWPrefix = 1 AND PrefixId = 'PAW') OR #IncludePAWPrefix = 0)
OR ((#IncludeRPLPrefix = 1 AND PrefixId = 'RPL') OR #IncludeRPLPrefix = 0)))
Which resulted in all rows being returned no matter what was selected. Can someone tell me where I am going wrong?
I believe this is the correct rearrangement. Trickier problem than it first appears. The issue was seperating lines like ((#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR #IncludeSEWPrefix = 0) with AND meant that if two includes were true, a row would need to have both PrefixId's, which can't happen. And if you separated them with OR, then having just one include false, means that every row will pass. So instead, check that a row has the prefix of any that are included, otherwise all includes have to be off.
WHERE EffectiveDate BETWEEN #StartDate AND #EndDate
AND
(
(#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR
(#IncludePAWPrefix = 1 AND PrefixId = 'PAW') OR
(#IncludeRPLPrefix = 1 AND PrefixId = 'RPL') OR
(#IncludeSEWPrefix = 0 AND #IncludePAWPrefix = 0 AND #IncludeRPLPrefix = 0)
)
Try this
WHERE
(EffectiveDate BETWEEN #StartDate AND #EndDate)
AND
(
(#IncludeSEWPrefix = 1 AND PrefixId = 'SEW' OR #IncludeSEWPrefix = 0) AND
(#IncludePAWPrefix = 1 AND PrefixId = 'PAW' OR #IncludePAWPrefix = 0) AND
(#IncludeRPLPrefix = 1 AND PrefixId = 'RPL' OR #IncludeRPLPrefix = 0)
)
You have more parenthesis than needed, it does not hurt but just be aware.
Maybe this can help:
WHERE (EffectiveDate BETWEEN #StartDate AND #EndDate)
AND ( ((#IncludeSEWPrefix = 1 AND PrefixId = 'SEW') OR (#IncludeSEWPrefix = 0 AND #PrefixId <> 'SEW'))
OR ((#IncludePAWPrefix = 1 AND PrefixId = 'PAW') OR (#IncludePAWPrefix = 0 AND #PrefixId <> 'PAW'))
OR ((#IncludeRPLPrefix = 1 AND PrefixId = 'RPL') OR (#IncludeRPLPrefix = 0 AND #PrefixId <> 'RPL'))
)