I need to improve my query which has more than 8 joins and consumes lot of total tablespace.
Following is the query:
select r.id, uc.contributor_full_name,s.code,
d.text, ucs.moderation_status, v.url
from review r, user_contribution uc, user_contribution_status ucs,
video v, description d, video_description vd, location_video lv,
accommodation_video av, system s
where r.user_contribution_id = ucs.user_contribution_id and
uc.id = ucs.user_contribution_id and
uc.system_id = s.id and
r.accommodation_id = av.accommodation_id or
r.location_id = lv.location_id and
av.video_id = v.id and
lv.video_id = v.id and
v.id = vd.video_id and
vd.description_id = d.id;
Is there any better way to write this query?
With a query like this it's possible Oracle will default to a whole lot of hash joins and full table scans, which may or may not be a good idea.
+1 to post the explain plan. Until then, don't upvote this answer!
I believe your query is equivalent to this, and it's possible that when you look at the explain plan that you'll see Oracle will convert it to something like this anyway:
select r.id
,uc.contributor_full_name,s.code
,d.text
,ucs.moderation_status
,v.url
from review r
join user_contribution_status ucs on r.user_contribution_id = ucs.user_contribution_id
join user_contribution uc on uc.id = ucs.user_contribution_id
join system s on uc.system_id = s.id
join accommodation_video av on r.accommodation_id = av.accommodation_id
join video_description vd on v.id = vd.video_id
join description d on vd.description_id = d.id
join video v on av.video_id = v.id
union all
select r.id
,uc.contributor_full_name,s.code
,d.text
,ucs.moderation_status
,v.url
from review r
join user_contribution_status ucs on r.user_contribution_id = ucs.user_contribution_id
join user_contribution uc on uc.id = ucs.user_contribution_id
join system s on uc.system_id = s.id
join location_video lv on r.location_id = lv.location_id
join video_description vd on v.id = vd.video_id
join description d on vd.description_id = d.id
join video v on lv.video_id = v.id;
Warning: I may have made some assumptions about constraints (e.g. PK, FK and not null) on some of the ID columns, esp. with regards to accommodation_video and location_video. I removed them from the subclauses with the assumption that they weren't necessary - but this assumption may be wrong.
Related
I have an issue with the IN instruction for a field...maybe you can see better than me what's happening.
The issue is on the waves parameter.
I got this in my database it's a configuration field...and this field contain a json
{
"typeId":"10,57",
"codeVague":"ITM1702A,ITMTEST"
}
This request inside sql return results:
SELECT v.id,v.`vague_code`, v.`date_fin_ultime`,m.*
FROM Vague v
INNER JOIN Enquete e ON e.`vague_id` = v.`id`
INNER JOIN Mission m ON m.id = e.`mission_id`
INNER JOIN Contrat c ON c.id = m.`contrat_id`
INNER JOIN `User` u ON u.`enqueteur_id` = e.`enqueteur_id`
INNER JOIN `PointDeVente` p ON p.id = e.`pdv_id`
WHERE v.`vague_code` IN ('ITM1702A','ITMTEST')
AND type_id IN (10,57)
But when I try to do the same from my symfony controller...I got an empty result
$sql="SELECT v.id,v.codeVague, v.date_fin_ultime,c.distance,p.adresse1,p.code_postal,p.ville,m
FROM McInvestigatorBundle:Vague v
INNER JOIN McInvestigatorBundle:Enquete e WITH e.vague_id = v.id
INNER JOIN McInvestigatorBundle:Mission m WITH m.id = e.mission_id
INNER JOIN McInvestigatorBundle:Contrat c WITH c.id = m.contrat
INNER JOIN McInvestigatorBundle:User u WITH u.enqueteur_id = e.enqueteur_id
INNER JOIN McInvestigatorBundle:PointDeVente p WITH p.id = e.pdv_id
WHERE v.codeVague IN (:waves)
AND e.type_id IN (:type_id)
AND m.enqueteur_id=:enq_id
ORDER BY m.date_rea_prev ASC";
$results= $em->createQuery($sql)->setParameters([
'waves' => $waves,
'type_id' => $type_id,
'enq_id' => $enq_id,
])->getResult();
The strange thing is that I got no issue with type_id, it works fine.
But, the waves field it's not the same story....
In fact, it works only if I have only one value in the json
"codeVague":"ITM1702A" is working
"codeVague":"ITM1702A,ITMTEST" is not working.
I already tried those strings in $waves.
"ITM1702A,ITMTEST" and "'ITM1702A','ITMTEST'" and "'ITM1702A,ITMTEST'"
Thanks you for your help !
EDIT: Problem solved, thanks Veve.
Can anybody help me how to find a component existence in all layers and models installed in that layer. i.e find all the layers and models in which a particular component(ax 2012) exists.
For example how to find all the layers and models in which CustTable exists.
Is there any class or table that stores this information.
please help me. Thanks in advance.
Comment is limited :(
Do you need to search through source code? Are you searching for merge candidates? Tell me your business requirement.
Here is the query returning elements that contains CustTable within selected models:
SELECT
me.Name ElementName
, Layer.Name Layer
, mm.Name ModelName
, ElementTypes.ElementTypeName
FROM ModelElement me
JOIN ModelElementData med
ON med.ElementHandle = me.ElementHandle
AND me.ParentHandle = 0 -- only root elements
JOIN ModelManifest mm
ON mm.ModelId=med.ModelId
JOIN Layer
ON Layer.Id = med.LayerId
JOIN ElementTypes
ON me.ElementType = ElementTypes.ElementType
WHERE EXISTS (
SELECT null
FROM ModelElement child
JOIN Sources s
ON s.SourceHandle = child.ElementHandle
AND s.LayerId = med.LayerId
AND child.RootHandle = med.ElementHandle
WHERE cast([SourceText] as nvarchar(max)) like '%CustTable%'
)
AND mm.Name IN ('Foundation','I4C')
You can try search within _model databese with next query (this searcehs all code references - table, class, form, dataset, ...):
SELECT TOP 1000 [SourceHandle]
, met.ElementTypeName
, ro.Name object
, me.Name method
, l.Name Layer
, mm.Name Model
, cast([SourceText] as nvarchar(max)) sourceTxt
FROM [Sources] s
join ModelElement me on me.ElementHandle=s.SourceHandle
join ElementTypes met on met.ElementType=me.ElementType
join ModelElement ro on ro.ElementHandle=me.RootHandle
left join ModelElementData med on med.ElementHandle=s.SourceHandle and med.LayerId=s.LayerId and med.ElementHandle=me.ElementHandle
left join Layer l on l.Id=s.LayerId
left join ModelManifest mm on mm.ModelId=med.ModelId
WHERE cast([SourceText] as nvarchar(max)) like '%CustTable%'
If you need all records, remove TOP 1000.
SELECT DISTINCT
ro.Name object,
ro.ElementType type,
l.Name Layer,
mm.Name Model
FROM Sources s
join ModelElement me on
me.ElementHandle = s.SourceHandle
join ElementTypes met
on met.ElementType = me.ElementType
join ModelElement ro
on ro.ElementHandle = me.RootHandle
left join ModelElementData med
on med.ElementHandle = s.SourceHandle
and med.LayerId = s.LayerId
and med.ElementHandle = me.ElementHandle
left join Layer l
on l.Id = s.LayerId
left join ModelManifest mm
on mm.ModelId = med.ModelId
where ro.Name = 'InventDim' order by mm.Name, ro.ElementType
In addition to the query suggested by the authors, a small change was made according to my requirement is giving the right results.
I need to select the MCUs table if UserID = 7 does not exist in the table. Please help me, what am I doing wrong?
SELECT
MCUs.MCUID
FROM
CASE
WHEN ReqMCUDevs.UserID = 7 THEN
MCUs
INNER JOIN MCUDevs
ON MCUs.MCUID = MCUDevs.MCUID
INNER JOIN ReqMCUDevs
ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
ELSE
MCUs
END
I need the resunt ot this query if UserID=7 exists
SELECT
MCUs.MCUID
FROM
MCUs
INNER JOIN MCUDevs
ON MCUs.MCUID = MCUDevs.MCUID
INNER JOIN ReqMCUDevs
ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
WHERE
ReqMCUDevs.UserID = 7
and this query if not
SELECT
MCUs.MCUID
FROM
MCUs
database schema:
The easiest solution is to use two different queries
db = sqlite3.connect("..\\DB.db", isolation_level = None);
c = db.cursor()
#...
c.execute("SELECT UserID FROM ReqMCUDevs WHEN UserID = ?", (UserID,))
if c.fetchall() == []:
c.execute("SELECT MCUID FROM MCUs")
else:
c.execute("""SELECT MCUID FROM MCUDevs
JOIN ReqMCUDevs ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity <= MCUDevs.Quantity
WHERE ReqMCUDevs.UserID = ?""", (UserID,))
but it is really not the answer
CASE works only in expressions (i.e., to compute a value); it is not possible to change the basic structure of a query conditionally.
However, there are different mechanisms to get what you want.
First, the query with the joins does not actually return anything from the joined tables, so it is possible to rewrite it with a subquery:
SELECT Name,
Price
FROM MCUs
WHERE MCUID IN (SELECT MCUID
FROM MCUDevs
JOIN ReqMCUDevs ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
WHERE ReqMCUDevs.UserID = 7)
ORDER BY Price
Now, we want to ignore this WHERE filter if the subquery is empty.
This can be done with a separate check:
SELECT Name,
Price
FROM MCUs
WHERE MCUID IN (SELECT MCUID
FROM MCUDevs
JOIN ReqMCUDevs ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
WHERE ReqMCUDevs.UserID = 7)
OR NOT EXISTS (SELECT MCUID
FROM MCUDevs
JOIN ReqMCUDevs ON MCUDevs.DevID = ReqMCUDevs.DevID
AND ReqMCUDevs.Quantity >= MCUDevs.Quantity
WHERE ReqMCUDevs.UserID = 7)
ORDER BY Price
In Visual Studio 2010 with ASP.NET 4, I am trying to join several tables together to put the results in a gridview and details view with sqldatasource. In the sqldatasource wizard I have chosen to specify a custom SQL statement or stored procedure and then in the Query Builder to define complex queries such as JOINs, I have tried to generate a SQL statement to join the problem table with speficific columns from other tables. But when I try to test the query I get an error message which says "Cannot call methods on varchar". I am new to sql statements so please can you advise on what is wrong with the statement.
Here is the generated sql statement below
SELECT Problem.ProblemID, Problem.CustomerID, Problem.Summary,
Problem.DateLogged, Problem.DateUpdated, Status.Status, Priority.Priority,
Technician.Name, Technician.Surname, [Skill Group].[Skill Group],
HelpdeskOperator.Name AS Expr1,
HelpdeskOperator.Surname AS Expr2, Problem.NoteID, Problem.ResolutionID
FROM Problem
INNER JOIN Status ON Problem.StatusID = Status.Status.StatusID
INNER JOIN HelpdeskOperator ON
Problem.HelpdeskID = HelpdeskOperator.HelpdeskID AND Status.StatusID = HelpdeskOperator.StatusID
INNER JOIN Priority ON Problem.PriorityID = Priority.PriorityID
INNER JOIN [Skill Group] ON Problem.SkillGroupID = [Skill Group].SkillGroupID
INNER JOIN Technician ON Problem.ProblemID = Technician.ProblemID
AND Status.StatusID = Technician.StatusID AND
Priority.PriorityID = Technician.PriorityID
AND [Skill Group].SkillGroupID = Technician.SkillGroupID
Thank you in advance
Fixed your query:
SELECT p.ProblemID, p.CustomerID, p.Summary, p.DateLogged, p.DateUpdated, s.Status, pr.Priority, t.Name, t.Surname,
sg.* , ho.Name AS Expr1, ho.Surname AS Expr2, p.NoteID, p.ResolutionID
FROM Problem p
INNER JOIN Status s ON p.StatusID = s.StatusID
INNER JOIN HelpdeskOperator ho ON p.HelpdeskID = ho.HelpdeskID AND s.StatusID = ho.StatusID
INNER JOIN Priority pr ON p.PriorityID = pr.PriorityID
INNER JOIN [Skill Group] sg ON p.SkillGroupID = sg.SkillGroupID
INNER JOIN Technician t ON p.ProblemID = t.ProblemID AND s.StatusID = t.StatusID AND pr.PriorityID = t.PriorityID
AND sg.SkillGroupID = t.SkillGroupID
You had duplicate table identifier in your join clause Status.Status.StatusID
I doubt that your Skill Group table contains column [Skill Group] so changed it to return all values from Skill Group
I just think those were the errors, if not I will need more info about your query and table structure.
EDIT:
First it did not return anything for HelpdeskOperator, look at our query:
INNER JOIN HelpdeskOperator ho ON p.HelpdeskID = ho.HelpdeskID AND s.StatusID = ho.StatusID
that meanse that here is no such HelpdeskOperator record that is assigned to our problem AND statusid, so either problem id points to noexisting helpdeskoperator or statusid of
this operator is different that problem status id.
next is Skill Group
INNER JOIN [Skill Group] sg ON p.SkillGroupID = sg.SkillGroupID
again our problem point to no existing skill group
then Technican
INNER JOIN Technician t ON p.ProblemID = t.ProblemID AND s.StatusID = t.StatusID AND pr.PriorityID = t.PriorityID
AND sg.SkillGroupID = t.SkillGroupID
here is more work as more checks, technicas must be assigned to our problem with given status and priorityt and be in skill group, BUT our skill group is null? so to check if
there is technican for our problem remove AND sg.SkillGroupID = t.SkillGroupID so you get
INNER JOIN Technician t ON p.ProblemID = t.ProblemID AND s.StatusID = t.StatusID AND pr.PriorityID = t.PriorityID
and see if now we get any technican.
I hope this points you into right direction. You must be sure that there are matching record in every joining table.
I've looked all around and spent way to long trying to convert this SQL statement into a Linq statement in VB. I'm sure it would be a good example for others out there - the statement is trying to pull products that have a many-to-many relationship with product categories, and the categories have a hierarchy of parents/children.
Here is the query I am trying to convert:
SELECT P.ProductID, P.ProductName, P.ProductSlug, P.PartNumber
FROM Products AS P
INNER JOIN Products_Categories AS PC ON PC.ProductID = P.ProductID
INNER JOIN Categories AS C ON PC.CategoryID = C.CategoryID
LEFT OUTER JOIN Categories AS P_Cats ON P_Cats.CategoryID = C.Parent
WHERE (C.CategoryID = 9) OR (C.Parent = 9) OR (P_Cats.Parent = 9)
I can get up to the point where I am trying to say "WHERE ... (P_Cats.Parent = 9)" but can't figure that part out.
THANKS!
Figured it out right after posting the question, but here is the answer in case anyone else finds it helpful:
Dim query = (From products In db.Products _
Join PC In db.Products_Categories On PC.ProductID Equals products.ProductID _
Join C In db.Categories On PC.CategoryID Equals C.CategoryID _
Group Join cat In db.Categories On cat.CategoryID Equals C.Parent Into C_Parents = Group _
From cParents In C_Parents.DefaultIfEmpty() _
Where (C.CategoryID = categoryID Or C.Parent = categoryID Or cParents.CategoryID = categoryID) _
And products.IsDeleted = False)
It was the line "From cParents In C_Parents.DefaultIfEmpty()" that I was leaving out.