I am quite new to PL/SQL.
I am using the following nested CASE statement in a SELECT query. This follows the WHERE clause.
However, the query takes about 6 minutes to complete because of this nesting. If at least one CASE block is removed the query only takes about 1 minute to complete.
Is there any way to optimize this query?
(case
when a = 'STAGE PAYMENT' then
'Y'
when b not IN ('To be Received', 'Received') then
'N'
when c != (d - NVL(e, 0) - NVL(f, 0) - NVL(g, 0)) then
'Y'
when NVL(h, 0) + NVL(i, 0) + NVL(j, 0) <> 0 then
case
when c != k then
'Y'
when (-l != NVL(e, 0) + NVL(f, 0) + NVL(g, 0) + NVL(m, 0)) then
'Y'
else 'N'
end
else 'N'
end = 'Y')
I have tried using IF-ELSE blocks, but it did not do any good.
What about aggregating the nested cases in the parent case with ANDs?
(case
when a = 'STAGE PAYMENT' then
'Y'
when b not IN ('To be Received', 'Received') then
'N'
when c != (d - NVL(e, 0) - NVL(f, 0) - NVL(g, 0)) then
'Y'
when NVL(h, 0) + NVL(i, 0) + NVL(j, 0) <> 0 and c != k then
'Y'
when NVL(h, 0) + NVL(i, 0) + NVL(j, 0) <> 0 and (-l != NVL(e, 0) + NVL(f, 0) + NVL(g, 0) + NVL(m, 0)) then
'Y'
-- this serves as else 'N' in your code
when NVL(h, 0) + NVL(i, 0) + NVL(j, 0) <> 0 then
'N'
else 'N'
end = 'Y')
Related
I want this to return a value even if some values do not exist
TO_CHAR((100-NVL(CO2+CO+MOIST+NH3_PPM+NH3+CH4+N2+AR,0)),'99.09') as "H2",
To me, it looks as if you wanted multiple NVLs:
TO_CHAR((100 - (
NVL(CO2 , 0) +
NVL(CO , 0) +
NVL(MOIST , 0) +
NVL(NH3_PPM, 0) +
NVL(NH3 , 0) +
NVL(CH4 , 0) +
NVL(N2 , 0) +
NVL(AR , 0)
), '99.09') AS h2
Can someone tell me what is the use of last 'Y' in the " end = 'Y') "
( case
when a = 'STAGE PAYMENT' then
'Y'
when b not IN ('To be Received', 'Received') then
'N'
when c != (d - NVL(e, 0) - NVL(f, 0) - NVL(g, 0)) then
'Y'
when NVL(h, 0) + NVL(i, 0) + NVL(j, 0) <> 0 then
case
when c != k then
'Y'
when (-l != NVL(e, 0) + NVL(f, 0) + NVL(g, 0) + NVL(m, 0)) then
'Y'
else 'N'
end
else 'N'
end = 'Y')
Also, is there any way of optimizing this?
Thanks!
Last end = 'Y') is nothing but the comparision.
Your case statement is generating one value based on condition and if it is Y then that condition will be statisfied and row will be considered in the result.
Lets say, If a = 'STAGE PAYMENT' is true for some record then your case statement will generate Y as output, which will be again compared with last end = 'Y') and returns true.
Cheers!!
As your case statement is part of the where clause, that = 'Y' is there to form the predicate.
Predicates most often have the form of <some value> <comparison operator> <other value> (there are exceptions, most notably regexp_like), where the <some value> and <other value> can be columns, functions, literal values, expressions, variables, etc.
Your case expression is simply taking up the place of the <some value>, i.e.:
select ...
from ...
where <some_col> = 1
and case .... end = 'Y'
I am trying to make an octree for randomly distributed set of particles. I have been trying to find where Stack Overflow Error appears whole day, but it was in vain. Could you please help me? The problem should be somewhere in (c == [0]) && (a > 0) part, however, I have no idea where. Thank you in advance!
type particle
R::Vector{Float64} # coordinates of the particle
m::Float64 # mass of the particle
a_tree::Float64 # acceleration of particle calculated from tree
a_exact::Float64 # acceleration of particle calculated by exact summation
end
type node
parent::Int64 # node's parent number
children::Vector{Int64} # set of childrens' numbers
l::Float64 # size of the node
R::Vector{Float64} # radius of geometric center
m::Float64 # total mass of the node
ptcl::Int64 # pointer to the particle in it
end
function problem3_2(N::Int64)
particles = Vector{particle}(N) # Basically, our system
tree = Vector{node}(1) # Initial tree (root)
tree[1] = node(0,[0],1.0,[0.0,0.0,0.0],0.0,0)
for i in eachindex(particles)
particles[i] = particle([rand() - 1/2, rand() - 1/2, rand() - 1/2], 1.0, 0.0, 0.0)
tree = InsertParticle(i,1,tree,particles)
end
return tree
end
function InsertParticle(i::Int64,k::Int64,tree,particles)
c = tree[k].children
a = tree[k].ptcl
if (c == [0]) && (a == 0)
tree[k].ptcl = i
elseif (c == [0]) && (a > 0)
j_1 = length(tree) + DetermOctant(particles[tree[k].ptcl],tree[k])
j_2 = length(tree) + DetermOctant(particles[i],tree[k])
tree[k].children = [x for x in length(tree)+1:length(tree)+8]
for p = 1:8
push!(tree,node(k,[0],tree[k].l/2,[0.0,0.0,0.0],0.0,0))
if (p == 1) || (p == 4) || (p == 5) || (p == 8)
tree[k+p].R[1] = tree[k].R[1] + tree[k+p].l/2
else
tree[k+p].R[1] = tree[k].R[1] - tree[k+p].l/2
end
if (p == 1) || (p == 2) || (p == 5) || (p == 6)
tree[k+p].R[2] = tree[k].R[2] + tree[k+p].l/2
else
tree[k+p].R[2] = tree[k].R[2] - tree[k+p].l/2
end
if (p == 1) || (p == 2) || (p == 3) || (p == 4)
tree[k+p].R[3] = tree[k].R[3] + tree[k+p].l/2
else
tree[k+p].R[3] = tree[k].R[3] - tree[k+p].l/2
end
end
InsertParticle(tree[k].ptcl,j_1,tree,particles)
InsertParticle(i,j_2,tree,particles)
tree[k].ptcl = 0
elseif (c != [0])
j = DetermOctant(particles[i],tree[k])
InsertParticle(i,tree[k].children[j],tree,particles)
end
return tree
end
function DetermOctant(x::particle,y::node)
c1 = y.R[1]; c2 = y.R[2]; c3 = y.R[3]
x1 = sign(x.R[1] - c1); x2 = sign(x.R[2] - c2); x3 = sign(x.R[3] - c3)
if (x1 > 0) && (x2 > 0) && (x3 > 0)
n = 1
elseif (x1 < 0) && (x2 > 0) && (x3 > 0)
n = 2
elseif (x1 < 0) && (x2 < 0) && (x3 > 0)
n = 3
elseif (x1 > 0) && (x2 < 0) && (x3 > 0)
n = 4
elseif (x1 > 0) && (x2 > 0) && (x3 < 0)
n = 5
elseif (x1 < 0) && (x2 > 0) && (x3 < 0)
n = 6
elseif (x1 < 0) && (x2 < 0) && (x3 < 0)
n = 7
else
n = 8
end
return n
end
Basically, I do know that the error should be somewhere here:
function InsertParticle(i::Int64,k::Int64,tree,particles)
c = tree[k].children
a = tree[k].ptcl
if (c == [0]) && (a == 0)
tree[k].ptcl = i
elseif (c == [0]) && (a > 0)
j_1 = length(tree) + DetermOctant(particles[tree[k].ptcl],tree[k])
j_2 = length(tree) + DetermOctant(particles[i],tree[k])
tree[k].children = [x for x in length(tree)+1:length(tree)+8]
for p = 1:8
push!(tree,node(k,[0],tree[k].l/2,[0.0,0.0,0.0],0.0,0))
if (p == 1) || (p == 4) || (p == 5) || (p == 8)
tree[k+p].R[1] = tree[k].R[1] + tree[k+p].l/2
else
tree[k+p].R[1] = tree[k].R[1] - tree[k+p].l/2
end
if (p == 1) || (p == 2) || (p == 5) || (p == 6)
tree[k+p].R[2] = tree[k].R[2] + tree[k+p].l/2
else
tree[k+p].R[2] = tree[k].R[2] - tree[k+p].l/2
end
if (p == 1) || (p == 2) || (p == 3) || (p == 4)
tree[k+p].R[3] = tree[k].R[3] + tree[k+p].l/2
else
tree[k+p].R[3] = tree[k].R[3] - tree[k+p].l/2
end
end
InsertParticle(tree[k].ptcl,j_1,tree,particles)
InsertParticle(i,j_2,tree,particles)
tree[k].ptcl = 0
elseif (c != [0])
j = DetermOctant(particles[i],tree[k])
InsertParticle(i,tree[k].children[j],tree,particles)
end
return tree
end
However, I cannot see where the infinite loop appears. Sorry for bringing these all here in a such form, I just want to avoid XY-problem.
Thank you in advance!
So I have this function:
public static BaseList GetVersesByChapterVerseRanges(string translation, BaseList criteriaList)
{
BaseList returnValue = new BaseList();;
if(criteriaList.Count() > 0)
{
List<VerseMaster.BusinessLayer.Vers> queryList = new List<Vers>();
int bookId = criteriaList[0].Book.BookId;
int StartChapter = criteriaList[0].StartChapter;
int EndChapter = criteriaList[0].EndChapter;
int StartVerse = criteriaList[0].StartChapterStartVerse;
int EndVerse = criteriaList[0].EndChapterEndVerse;
var searchQuery = (from v in VerseMaster.BusinessLayer.Controller.Controller.VerseMasterEntities.Verses where v.Translation.ToLower().StartsWith(translation.ToLower()) && v.BookId == bookId && v.ChapterNumber >= StartChapter && v.ChapterNumber <= EndChapter && (v.ChapterNumber == StartChapter ? (v.VerseNumber >= StartVerse) : true) && (v.ChapterNumber == EndChapter ? (v.VerseNumber <= EndVerse) : true) orderby v.ChapterNumber, v.VerseNumber ascending select v);
for(int i = 1; i < criteriaList.Count(); i++)
{
bookId = criteriaList[i].Book.BookId;
StartChapter = criteriaList[i].StartChapter;
EndChapter = criteriaList[i].EndChapter;
StartVerse = criteriaList[i].StartChapterStartVerse;
EndVerse = criteriaList[i].EndChapterEndVerse;
VerseMaster.BusinessLayer.DataObjects.Helper.VerseSearchCriteria criteria = criteriaList[i];
searchQuery = (System.Linq.IOrderedQueryable<VerseMaster.BusinessLayer.Vers>)searchQuery.Concat(from v in VerseMaster.BusinessLayer.Controller.Controller.VerseMasterEntities.Verses where v.Translation.ToLower().StartsWith(translation.ToLower()) && v.BookId == bookId && v.ChapterNumber >= StartChapter && v.ChapterNumber <= EndChapter && (v.ChapterNumber == StartChapter ? (v.VerseNumber >= StartVerse) : true) && (v.ChapterNumber == EndChapter ? (v.VerseNumber <= EndVerse) : true) orderby v.ChapterNumber, v.VerseNumber ascending select v);
}
string traceString = ((System.Data.Objects.ObjectQuery)searchQuery).ToTraceString();
foreach (var entVerse in searchQuery)
{
VerseMaster.BusinessLayer.DataObjects.IVerse verse = new VerseMaster.BusinessLayer.DataObjects.Verse();
LoadVerseFromEntityVerse(ref verse, entVerse);
Console.Write(String.Format("Chapter={0} Verse={1} Text={2}\n", entVerse.ChapterNumber, entVerse.VerseNumber, entVerse.Verse));
//returnValue.Add((VerseMaster.BusinessLayer.DataObjects.Verse)verse);
}
}
return returnValue;
}
So for some reason I had to convert each of the parameters that go into the linq query into standard ints because of an error, not sure if its related. So the generated sql is:
SELECT
[UnionAll2].[C1] AS [C1],
[UnionAll2].[C2] AS [C2],
[UnionAll2].[C3] AS [C3],
[UnionAll2].[C4] AS [C4],
[UnionAll2].[C5] AS [C5],
[UnionAll2].[C6] AS [C6]
FROM (SELECT
[UnionAll1].[VerseId] AS [C1],
[UnionAll1].[ChapterNumber] AS [C2],
[UnionAll1].[VerseNumber] AS [C3],
[UnionAll1].[Verse] AS [C4],
[UnionAll1].[Translation] AS [C5],
[UnionAll1].[BookId] AS [C6]
FROM (SELECT
[Extent1].[VerseId] AS [VerseId],
[Extent1].[ChapterNumber] AS [ChapterNumber],
[Extent1].[VerseNumber] AS [VerseNumber],
[Extent1].[Verse] AS [Verse],
[Extent1].[Translation] AS [Translation],
[Extent1].[BookId] AS [BookId]
FROM [dbo].[Verses] AS [Extent1]
WHERE (( CAST(CHARINDEX(LOWER(#p__linq__0), LOWER([Extent1].[Translation])) AS int)) = 1) AND ([Extent1].[BookId] = #p__linq__1) AND ([Extent1].[ChapterNumber] >= #p__linq__2) AND ([Extent1].[ChapterNumber] <= #p__linq__3) AND ((CASE WHEN ([Extent1].[ChapterNumber] = #p__linq__4) THEN CASE WHEN ([Extent1].[VerseNumber] >= #p__linq__5) THEN cast(1 as bit) WHEN ( NOT ([Extent1].[VerseNumber] >= #p__linq__5)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1) AND ((CASE WHEN ([Extent1].[ChapterNumber] = #p__linq__6) THEN CASE WHEN ([Extent1].[VerseNumber] <= #p__linq__7) THEN cast(1 as bit) WHEN ( NOT ([Extent1].[VerseNumber] <= #p__linq__7)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1)
UNION ALL
SELECT
[Extent2].[VerseId] AS [VerseId],
[Extent2].[ChapterNumber] AS [ChapterNumber],
[Extent2].[VerseNumber] AS [VerseNumber],
[Extent2].[Verse] AS [Verse],
[Extent2].[Translation] AS [Translation],
[Extent2].[BookId] AS [BookId]
FROM [dbo].[Verses] AS [Extent2]
WHERE (( CAST(CHARINDEX(LOWER(#p__linq__8), LOWER([Extent2].[Translation])) AS int)) = 1) AND ([Extent2].[BookId] = #p__linq__9) AND ([Extent2].[ChapterNumber] >= #p__linq__10) AND ([Extent2].[ChapterNumber] <= #p__linq__11) AND ((CASE WHEN ([Extent2].[ChapterNumber] = #p__linq__12) THEN CASE WHEN ([Extent2].[VerseNumber] >= #p__linq__13) THEN cast(1 as bit) WHEN ( NOT ([Extent2].[VerseNumber] >= #p__linq__13)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1) AND ((CASE WHEN ([Extent2].[ChapterNumber] = #p__linq__14) THEN CASE WHEN ([Extent2].[VerseNumber] <= #p__linq__15) THEN cast(1 as bit) WHEN ( NOT ([Extent2].[VerseNumber] <= #p__linq__15)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1)) AS [UnionAll1]
UNION ALL
SELECT
[Extent3].[VerseId] AS [VerseId],
[Extent3].[ChapterNumber] AS [ChapterNumber],
[Extent3].[VerseNumber] AS [VerseNumber],
[Extent3].[Verse] AS [Verse],
[Extent3].[Translation] AS [Translation],
[Extent3].[BookId] AS [BookId]
FROM [dbo].[Verses] AS [Extent3]
WHERE (( CAST(CHARINDEX(LOWER(#p__linq__16), LOWER([Extent3].[Translation])) AS int)) = 1) AND ([Extent3].[BookId] = #p__linq__17) AND ([Extent3].[ChapterNumber] >= #p__linq__18) AND ([Extent3].[ChapterNumber] <= #p__linq__19) AND ((CASE WHEN ([Extent3].[ChapterNumber] = #p__linq__20) THEN CASE WHEN ([Extent3].[VerseNumber] >= #p__linq__21) THEN cast(1 as bit) WHEN ( NOT ([Extent3].[VerseNumber] >= #p__linq__21)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1) AND ((CASE WHEN ([Extent3].[ChapterNumber] = #p__linq__22) THEN CASE WHEN ([Extent3].[VerseNumber] <= #p__linq__23) THEN cast(1 as bit) WHEN ( NOT ([Extent3].[VerseNumber] <= #p__linq__23)) THEN cast(0 as bit) END ELSE cast(1 as bit) END) = 1)) AS [UnionAll2]
So the problem is that for some reason its treating each of the parameters I give it as if I sent 3 sets of the same parameter and concatenated so its returning the same set of verses 3 times. I'm not sure why its doing this as I am not an expert of linq or the entity framework, any suggestions?
This is a very tricky example of the modified closure issue. In the for loop you generate a query part that uses the variables bookId etc. At the time that your query is executed it uses the values that these variables have at that moment, which are the values after the last iteration of the loop. (The tricky part is that usually the loop variable is captured, but here it is about variables that were declared outside the loop scope).
It would be different if you declared the variables within the for loop, because each query part would capture its own instance of the variable (which is called a closure).
The good news: you can do this and at the same time clean up your code!
if(criteriaList.Count() > 0)
{
IQueryable<Verse> baseQuery = null;
for(int i = 0; i < criteriaList.Count(); i++) // starting i = 0 now !
{
int bookId = criteriaList[0].Book.BookId;
int StartChapter = criteriaList[0].StartChapter;
int EndChapter = criteriaList[0].EndChapter;
int StartVerse = criteriaList[0].StartChapterStartVerse;
int EndVerse = criteriaList[0].EndChapterEndVerse;
searchQuery = (IOrderedQueryable<Vers>)searchQuery.Concat(
from v in Controller.Controller.VerseMasterEntities.Verses
where v.Translation.ToLower().StartsWith(translation.ToLower())
&& v.BookId == bookId
&& v.ChapterNumber >= StartChapter
&& v.ChapterNumber <= EndChapter
&& (v.ChapterNumber == StartChapter ? (v.VerseNumber >= StartVerse) : true)
&& (v.ChapterNumber == EndChapter ? (v.VerseNumber <= EndVerse) : true)
select v);
if (i == 0)
baseQuery = searchQuery;
else
baseQuery = baseQuery.Concat(searchQuery);
}
...
(do the ordering later)
The following LINQ to Entities query slows down substantially when the commented line below is included in the query. Is there a better way to phrase this?
The 'OR' clause should only take into account the following lines:
((o.Type_ID == (int) RecordEnums.RecordType.Lead) && (o.Item_ID == l1.Lead_ID))
|| ((o.Type_ID == (int)RecordEnums.RecordType.Opportunity)(o.Item_ID == o1.Opportunity_ID))
Full Query
return withItemsPending
? (from l1 in db.Leads
from o1 in db.Opportunities.Where(x => (x.Lead_ID == l1.Lead_ID) && (x.Company_ID == companyId)).DefaultIfEmpty()
from l2
in
db.Tasks.Where(
o =>
((o.IsCompleted ?? false) == false) &&
(o.TaskType_ID == typeId) &&
((o.Type_ID == (int) RecordEnums.RecordType.Lead) && (o.Item_ID == l1.Lead_ID))
//|| ((o.Type_ID == (int)RecordEnums.RecordType.Opportunity) && (o.Item_ID == o1.Opportunity_ID))
&&
(o.Due_Date > EntityFunctions.AddDays(DateTime.Now, -1)))
where (l1.Company_ID == companyId)
select l1)
: (from l1 in db.Leads where (0 == 1) select l1);
}
Here's the offending query:
SELECT Extent1.Lead_ID
FROM Leads AS Extent1 LEFT OUTER JOIN
Opportunities AS Extent2 ON Extent2.Lead_ID = Extent1.Lead_ID AND Extent2.Company_ID = 118 INNER JOIN
Tasks AS Extent3 ON 0 = (CASE WHEN ([Extent3].[IsCompleted] IS NULL) THEN CAST(0 AS bit) ELSE [Extent3].[IsCompleted] END) AND Extent3.TaskType_ID = 1 AND
5 = Extent3.Type_ID AND Extent3.Item_ID = Extent1.Lead_ID OR
4 = Extent3.Type_ID AND Extent3.Item_ID = Extent2.Opportunity_ID AND Extent3.Due_Date > DATEADD(day, - 1, SysDateTime())
WHERE (Extent1.Company_ID = 118)
If what you want is "give me the items that are not completed AND are due later than yesterday AND are EITHER Lead OR Opportunity", you need to add extra brackets around the 2 statements you want to OR. What you are currently saying is "give me the items that are either not completed AND Lead OR Opportunity AND due later than yesterday".
The code will then be like this:
return withItemsPending
? (from l1 in db.Leads
from o1 in db.Opportunities.Where(x => (x.Lead_ID == l1.Lead_ID) && (x.Company_ID == companyId)).DefaultIfEmpty()
from l2
in
db.Tasks.Where(
o =>
((o.IsCompleted ?? false) == false) &&
(o.TaskType_ID == typeId) &&
(((o.Type_ID == (int) RecordEnums.RecordType.Lead) && (o.Item_ID == l1.Lead_ID))
|| ((o.Type_ID == (int)RecordEnums.RecordType.Opportunity) && (o.Item_ID == o1.Opportunity_ID)))
&&
(o.Due_Date > EntityFunctions.AddDays(DateTime.Now, -1)))
where (l1.Company_ID == companyId)
select l1)
: (from l1 in db.Leads where (0 == 1) select l1);
}