Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

view help 2

Status
Not open for further replies.

wbodger

Programmer
Apr 23, 2007
769
US
OK, I have been working on this view for a while. The view pulls all of the correct information, but it is painfully slow (48 seconds to build a view just under 100k rows). I know at least part of the problem is that the underlying table structure was not well thought out ahead of time and unfortunately we cannot change it... Here is the full query
Code:
SELECT     PrimaryTbl.SpecimenID, COALESCE (SecondaryTbl.PptID, PrimaryTbl.PptID) AS pptid, 
	CASE 
		WHEN LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 1) = '0' THEN substring((COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid)), 2, 2) 
		ELSE LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 3) 
    END AS CollectionSiteID, 
    s.Abbreviation AS CollectionSiteName, 
    CASE 
		WHEN PrimaryTbl.parentspecimenid = '' THEN 'Parent' 
		ELSE 'Child' 
	END AS parentorchild, 
    PrimaryTbl.SpecimenSourceID,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues
    WHERE      (ElementID = 8) AND (Active = 1) AND (Value = PrimaryTbl.SpecimenSourceID)) AS SpecimenSourceName, 
    PrimaryTbl.SpecimenStoredID,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_18
    WHERE      (ElementID = 9) AND (Active = 1) AND (Value = PrimaryTbl.SpecimenStoredID)) AS SpecimenStoredName, 
    PrimaryTbl.Quantity, 
    CASE 
		WHEN PrimaryTbl.UnitID = 0 THEN 'unknown' 
		WHEN PrimaryTbl.UnitID = 1 THEN 'µl' 
		WHEN PrimaryTbl.UnitId = 2 THEN 'ml' 
	END AS Unit, 
    PrimaryTbl.CollectionDate, 
    PrimaryTbl.Comments, 
    PrimaryTbl.ParentSpecimenID, 
    CASE 
		WHEN PrimaryTbl.PptVisitType = 0 THEN SecondaryTbl.PptVisitType 
		ELSE PrimaryTbl.PptVisitType 
	END AS PptVisitType,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_17
    WHERE      (ElementID = 82) AND (Active = 1) AND 
    (Value = CASE 
				WHEN PrimaryTbl.PptVisitType = 0 THEN SecondaryTbl.PptVisitType 
				ELSE PrimaryTbl.PptVisitType 
			 END)) AS PptVisitTypeName, 
   PrimaryTbl.PptVisitDate, 
   PrimaryTbl.CurrentQuantity, 
   PrimaryTbl.CurrentQuantityUnitID,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_16
    WHERE      (ElementID = 47) AND (Active = 1) AND (Value = PrimaryTbl.CurrentQuantityUnitID)) AS CurrentQuantityUnitName, 
    PrimaryTbl.Concentration, 
    PrimaryTbl.ConcentrationUnitID,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_15
    WHERE      (ElementID = 42) AND (Active = 1) AND (Value = PrimaryTbl.ConcentrationUnitID)) AS ConcentrationUnitName, 
   PrimaryTbl.NumOfThawed, 
   L.SiteID AS StorageLabID,
   L.LabNameShort AS StorageLabName,
   PrimaryTbl.RefrigeratorID, 
   PrimaryTbl.BoxID, 
   PrimaryTbl.Row, 
   PrimaryTbl.Col, 
   --if specimenstoredid in 2,35,9, then fasting needs to be inherited from the parent
   Case
	WHEN PrimaryTbl.specimenstoredid in (2,9,35) THEN SecondaryTbl.Fasting
	ELSE PrimaryTbl.Fasting
	END AS Fasting,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_14
    WHERE      (ElementID = 434) AND (Active = 1) AND (Value = Case
		WHEN PrimaryTbl.specimenstoredid in (2,9,35) THEN SecondaryTbl.Fasting
		ELSE PrimaryTbl.Fasting
		END)) AS FastingName, 
    PrimaryTbl.Status,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_13
    WHERE      (ElementID = 29) AND (Active = 1) AND (Value = PrimaryTbl.Status)) AS StatusName, 
    PrimaryTbl.ReasonOfChange, 
    PrimaryTbl.ReasonOfDefective,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_12
    WHERE      (ElementID = 61) AND (Active = 1) AND (Value = PrimaryTbl.ReasonOfDefective)) AS ReasonOfDefectiveName, 
    PrimaryTbl.OtherReasonOfDefective, 
    PrimaryTbl.TubeSize, 
    PrimaryTbl.MainSelected,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195
    WHERE      (ProcessQuestionID = 422) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS SpecimensFrozenAtMinus70OrColder,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_11
    WHERE      (ElementID = 422) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_26
         WHERE      (ProcessQuestionID = 422) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS SpecimensFrozenAtMinus70OrColderName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_25
    WHERE      (ProcessQuestionID = 431) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS PQComments,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_24
    WHERE      (ProcessQuestionID = 435) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS SpecimenPlacedImmedOnIceOrAt4Celsius,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_10
    WHERE      (ElementID = 435) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_23
         WHERE      (ProcessQuestionID = 435) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS SpecimenPlacedImmedOnIceOrAt4CelsiusName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_22
    WHERE      (ProcessQuestionID = 438) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS FreezerNumberSpecimenStoredAt,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_21
    WHERE      (ProcessQuestionID = 439) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS SpecimenHemolyedLipemicIcteric,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_9
    WHERE      (ElementID = 439) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_20
         WHERE      (ProcessQuestionID = 439) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS SpecimenHemolyedLipemicIctericName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_19
    WHERE      (ProcessQuestionID = 442) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS TimeFromCollectionToFreezingHours,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_18
    WHERE      (ProcessQuestionID = 443) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS EquipmentFailureDeviationFromProtocol,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_8
    WHERE      (ElementID = 443) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_17
         WHERE      (ProcessQuestionID = 443) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS EquipmentFailureDeviationFromProtocolName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_16
    WHERE      (ProcessQuestionID = 450) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS VolumeRawUrineProcessed,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_15
    WHERE      (ProcessQuestionID = 451) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS SpecimenInverted,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_7
    WHERE      (ElementID = 451) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_14
         WHERE      (ProcessQuestionID = 451) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS SpecimenInvertedName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_13
    WHERE      (ProcessQuestionID = 454) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS SpecimenProcessedWithin,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_6
    WHERE      (ElementID = 454) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_12
         WHERE      (ProcessQuestionID = 454) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS SpecimenProcessedWithinName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_11
    WHERE      (ProcessQuestionID = 455) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS TissuePosition,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_5
    WHERE      (ElementID = 455) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_10
         WHERE      (ProcessQuestionID = 455) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS TissuePositionName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_9
    WHERE      (ProcessQuestionID = 456) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS StorageTemperature,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_4
    WHERE      (ElementID = 456) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_8
         WHERE      (ProcessQuestionID = 456) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS StorageTemperatureName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_7
    WHERE      (ProcessQuestionID = 457) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS ProcessingMethod,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_3
    WHERE      (ElementID = 457) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_6
         WHERE      (ProcessQuestionID = 457) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS ProcessingMethodName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_5
    WHERE      (ProcessQuestionID = 458) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS PathologyDeptBlockNumber,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_4
    WHERE      (ProcessQuestionID = 459) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS PrimaryTissueType,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_2
    WHERE      (ElementID = 459) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_3
         WHERE      (ProcessQuestionID = 459) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS PrimaryTissueTypeName,
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_2
    WHERE      (ProcessQuestionID = 460) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS SpecimenProcessedProtocol,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_1
    WHERE      (ElementID = 460) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_1
         WHERE      (ProcessQuestionID = 460) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS SpecimenProcessedProtocolName
FROM	dbo.tblSpecimenBank195 AS PrimaryTbl 
		LEFT OUTER JOIN dbo.tblSpecimenBank195 AS SecondaryTbl ON PrimaryTbl.ParentSpecimenID = SecondaryTbl.SpecimenID 
		INNER JOIN NewCompass.dbo.tblSite AS s ON s.SiteID = 
			(CASE 
				WHEN LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 1) 
                      = '0' THEN substring((COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid)), 2, 2) 
                ELSE LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 3) 
             END) LEFT JOIN tblLabs L on PrimaryTbl.LabID=L.LabID
The parts that I am particularly interested in are the two areas where I have to make subquery calls over and over to separate tables. For instance
Code:
  (SELECT     Answer
    FROM          dbo.tblSpecimenPQ195
    WHERE      (ProcessQuestionID = 422) AND (SpecimenID = PrimaryTbl.SpecimenID)) AS SpecimensFrozenAtMinus70OrColder,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_11
    WHERE      (ElementID = 422) AND (Value =
       (SELECT     Answer
         FROM          dbo.tblSpecimenPQ195 AS tblSpecimenPQ195_26
         WHERE      (ProcessQuestionID = 422) AND (SpecimenID = PrimaryTbl.SpecimenID)))) AS SpecimensFrozenAtMinus70OrColderName,
Uses the same code twice, once as the main subquery and then again as a nested subquery, and I have to do this like 16 times. I have tried this with a scalar valued function and it slowed it down massively. I have considered breaking this down into multiple steps, creating a few views and then creating an aggregate view, but I haven't been able to see where that would cut any time. Looking at the Execution Plan, there are no big time draws, but there are a bunch at about 3% on tblSpecimenPQ195. That table has a clustered index on ProcessQuestionID and SpecimenID. Any thoughts on what I might try to speed this up a bit?

Thanks,
wb
 
I made those changes and dropped the time on the ModifiedSQL to 3:56 (from 3:57) and the time on the Original SQL to :49 (from :50). However, if I drop the section that connects to tblSpecimenPQ195, then the time drops to :04

wb
 
on top of what you did..

can you also change some of the remaining subselects to the inner group as follows

Code:
		  ,max(case
		       when (meValues_1.ElementID = 8)   
		        AND (meValues_1.Active = '1') 
		        AND (meValues_1.Value = PrimaryTbl.SpecimenSourceID)
		            THEN meValues_1.ValueName
		       ELSE NULL
		       end) as SpecimenSourceName

....
	left outer join  dbo.tblMetaElementValues meValues_1
    on meValues_1.elementid in (8,9,47,42,29,16)
    and meValues_1.active = '1'
    and meValues_1.value in (PrimaryTbl.SpecimenSourceID
                            ,PrimaryTbl.CurrentQuantityUnitID
                            ,PrimaryTbl.ConcentrationUnitID
                            ,PrimaryTbl.Status
                            )

The above would be for
SpecimenSourceName
SpecimenStoredName
CurrentQuantityUnitName
ConcentrationUnitName
StatusName
ReasonOfDefectiveName

Add the case statements as required.


George what you think may be causing such delay now?

Regards

Frederico Fonseca
SysSoft Integrated Ltd

FAQ219-2884
FAQ181-2886
 
Frederico,

I'm really not sure. According to the execution plan, there were a lot of table scans on the smaller table, and the percentages appeared to be adding up, but it clearly didn't make (much) difference in performance.

It appears as though all of the execution plan steps involved with the larger table tblSpecimenPQ195 are all custered index seeks, which ought to be efficient.

My next guess is fragmentation causing a huge problem. It would have to be pretty bad to make this much difference though. It could also have something to do with statistics.

Since statistics are updated when the indexes are recreated, that's my next suggestion.

wbodger, can you please run the following (but only if it's not a busy time for your database).

Code:
dbcc dbreindex('tblSpecimenBank195')
dbcc dbreindex('tblSpecimenPQ195')

Honestly... I haven't even really looked at the query. I mean... it's huge, and ugly. I suspect the query could be written differently that would be more efficient.

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
I will make those changes and yes, it is a mess. Due in part to my SQL knowledge I am sure, but also due to the structure of the underlying tables. I will let you know what happens with those changes. Thank you again for your time!
 
OK, I have made those modifications to the query and I have re-indexed the tables. That query is now taking 6:54, with the original query taking 0:48. I don't get it.

wb
 
Can you try something for me? I'm thinking that it's time for me to take a closer look at the original query. It will be a lot easier to tweak things in stages, so don't get too excited that there will be a "magic bullet" type of solution. This is going to be a process.

First, run this query and tell me how long it takes.

Code:
Select SpecimenId,
       Max(Case When ProcessQuestionID = 422 Then Answer End) AS SpecimensFrozenAtMinus70OrColder,
       Max(Case When ProcessQuestionID = 431 Then Answer End) AS PQComments,
       Max(Case When ProcessQuestionID = 435 Then Answer End) AS SpecimenPlacedImmedOnIceOrAt4Celsius,
       Max(Case When ProcessQuestionID = 438 Then Answer End) AS FreezerNumberSpecimenStoredAt,
       Max(Case When ProcessQuestionID = 439 Then Answer End) AS SpecimenHemolyedLipemicIcteric,
       Max(Case When ProcessQuestionID = 442 Then Answer End) AS TimeFromCollectionToFreezingHours,
       Max(Case When ProcessQuestionID = 443 Then Answer End) AS EquipmentFailureDeviationFromProtocol,
       Max(Case When ProcessQuestionID = 450 Then Answer End) AS VolumeRawUrineProcessed,
       Max(Case When ProcessQuestionID = 451 Then Answer End) AS SpecimenInverted,
       Max(Case When ProcessQuestionID = 454 Then Answer End) AS SpecimenProcessedWithin,
       Max(Case When ProcessQuestionID = 455 Then Answer End) AS TissuePosition,
       Max(Case When ProcessQuestionID = 456 Then Answer End) AS StorageTemperature,
       Max(Case When ProcessQuestionID = 457 Then Answer End) AS ProcessingMethod,
       Max(Case When ProcessQuestionID = 458 Then Answer End) AS PathologyDeptBlockNumber,
       Max(Case When ProcessQuestionID = 459 Then Answer End) AS PrimaryTissueType,
       Max(Case When ProcessQuestionID = 460 Then Answer End) As SpecimenProcessedProtocol
From   dbo.tblSpecimenPQ195
Where  ProcessQuestionID In (422,431,435,438,439,442,443,450,451,454,455,456,457,458,459,460)
Group By SpecimenId

Then, create a new index on the dbo.tblSpecimenPQ195.

Code:
Create index idx_tblSpecimenPQ195_ProcessQuestionId On dbo.tblSpecimenPQ195(ProcessQuestionId) Include (SpecimenId, Answer)

Now, run the previous query again and tell me how long it takes.

The query should run a lot faster with the index added. If so, then I will integrate this query in to your larger query and then we can take another look at the execution time.

Make sense?

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
I'm sorry, the index I wanted you to create was this....

Code:
Create index idx_tblSpecimenPQ195_ProcessQuestionId On dbo.tblSpecimenPQ195(ProcessQuestionId, SpecimenId) Include (Answer)

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
The query took 2 seconds to run, but there is already an index with those columns in it.
 
but there is already an index with those columns in it.

Based on a post you made yesterday, you have....

[tt]
tblSpecimenPQ195 has this
IX_PQ_Answer195 SpecimenID, ProcessQuestionID, Answer
PK_tblSpecimenPQ195 SpecimenID, ProcessQuestionID
[/tt]

There is a big difference between "SpecimenID, ProcessQuestionID" and "ProcessQuestionID, SpecimenID".

Think of it this way. Suppose I hand you a phone book and ask you to find the phone number for anyone with a first name of George. Not so easy because phone books are sorted first by last name and then by first name. Indexed in SQL Server are the same way.





-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
OK, I did not realize that. Now, the way that you wrote the create index did not work. Why did you create the index with two fields and then include the third. Can I just create it with all three in the order specified?
 
I created the index with the fields in that order you specified and reran the query with the same result, 0:02.
 
I originally suggested that you INCLUDE(Answer) because it's not important (to this query) and Answer be sorted. INCLUDE columns first appeared in SQL Server 2005. An index with an include column instead of a 3rd key column would be a little more efficient in terms of updating the index.

[tt]Can I just create it with all three in the order specified? [/tt]

Yes.

Code:
Create index idx_tblSpecimenPQ195_ProcessQuestionId On dbo.tblSpecimenPQ195(ProcessQuestionId, SpecimenId, Answer)


-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
Can you post the execution plan for that query like you did with the others?

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
I also tried rewriting the query to see if I could simplify the joins. It crashed and burned.

Code:
SELECT PrimaryTbl.SpecimenID, COALESCE (SecondaryTbl.PptID, PrimaryTbl.PptID) AS pptid, 
	CASE 
		WHEN LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 1) = '0' THEN substring((COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid)), 2, 2) 
		ELSE LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 3) 
    END AS CollectionSiteID, 
    s.Abbreviation AS CollectionSiteName, 
    CASE 
		WHEN PrimaryTbl.parentspecimenid = '' THEN 'Parent' 
		ELSE 'Child' 
	END AS parentorchild, 
    PrimaryTbl.SpecimenSourceID,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues
    WHERE      (ElementID = 8) AND (Active = 1) AND (Value = PrimaryTbl.SpecimenSourceID)) AS SpecimenSourceName, 
    PrimaryTbl.SpecimenStoredID,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_18
    WHERE      (ElementID = 9) AND (Active = 1) AND (Value = PrimaryTbl.SpecimenStoredID)) AS SpecimenStoredName, 
    PrimaryTbl.Quantity, 
    CASE 
		WHEN PrimaryTbl.UnitID = 0 THEN 'unknown' 
		WHEN PrimaryTbl.UnitID = 1 THEN 'µl' 
		WHEN PrimaryTbl.UnitId = 2 THEN 'ml' 
	END AS Unit, 
    PrimaryTbl.CollectionDate, 
    PrimaryTbl.Comments, 
    PrimaryTbl.ParentSpecimenID, 
    CASE 
		WHEN PrimaryTbl.PptVisitType = 0 THEN SecondaryTbl.PptVisitType 
		ELSE PrimaryTbl.PptVisitType 
	END AS PptVisitType,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_17
    WHERE      (ElementID = 82) AND (Active = 1) AND 
    (Value = CASE 
				WHEN PrimaryTbl.PptVisitType = 0 THEN SecondaryTbl.PptVisitType 
				ELSE PrimaryTbl.PptVisitType 
			 END)) AS PptVisitTypeName, 
   PrimaryTbl.PptVisitDate, 
   PrimaryTbl.CurrentQuantity, 
   PrimaryTbl.CurrentQuantityUnitID,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_16
    WHERE      (ElementID = 47) AND (Active = 1) AND (Value = PrimaryTbl.CurrentQuantityUnitID)) AS CurrentQuantityUnitName, 
    PrimaryTbl.Concentration, 
    PrimaryTbl.ConcentrationUnitID,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_15
    WHERE      (ElementID = 42) AND (Active = 1) AND (Value = PrimaryTbl.ConcentrationUnitID)) AS ConcentrationUnitName, 
   PrimaryTbl.NumOfThawed, 
   L.SiteID AS StorageLabID,
   L.LabNameShort AS StorageLabName,
   PrimaryTbl.RefrigeratorID, 
   PrimaryTbl.BoxID, 
   PrimaryTbl.Row, 
   PrimaryTbl.Col, 
   --if specimenstoredid in 2,35,9, then fasting needs to be inherited from the parent
   Case
	WHEN PrimaryTbl.specimenstoredid in (2,9,35) THEN SecondaryTbl.Fasting
	ELSE PrimaryTbl.Fasting
	END AS Fasting,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_14
    WHERE      (ElementID = 434) AND (Active = 1) AND (Value = Case
		WHEN PrimaryTbl.specimenstoredid in (2,9,35) THEN SecondaryTbl.Fasting
		ELSE PrimaryTbl.Fasting
		END)) AS FastingName, 
    PrimaryTbl.Status,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_13
    WHERE      (ElementID = 29) AND (Active = 1) AND (Value = PrimaryTbl.Status)) AS StatusName, 
    PrimaryTbl.ReasonOfChange, 
    PrimaryTbl.ReasonOfDefective,
  (SELECT     ValueName
    FROM          dbo.tblMetaElementValues AS tblMetaElementValues_12
    WHERE      (ElementID = 61) AND (Active = 1) AND (Value = PrimaryTbl.ReasonOfDefective)) AS ReasonOfDefectiveName, 
    PrimaryTbl.OtherReasonOfDefective, 
    PrimaryTbl.TubeSize, 
    PrimaryTbl.MainSelected,
  CASE ProcessQuestionID WHEN 422 THEN Answer ELSE NULL END AS SpecimensFrozenAtMinus70OrColder,
  CASE ProcessQuestionID WHEN 422 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS SpecimensFrozenAtMinus70OrColderName,
  CASE ProcessQuestionID WHEN 431 THEN Answer ELSE NULL END AS PQComments,
  CASE ProcessQuestionID WHEN 435 THEN Answer ELSE NULL END AS SpecimenPlacedImmedOnIceOrAt4Celsius,
  CASE ProcessQuestionID WHEN 435 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS SpecimenPlacedImmedOnIceOrAt4CelsiusName,
  CASE ProcessQuestionID WHEN 438 THEN Answer ELSE NULL END AS FreezerNumberSpecimenStoredAt,
  CASE ProcessQuestionID WHEN 439 THEN Answer ELSE NULL END AS SpecimenHemolyedLipemicIcteric,
  CASE ProcessQuestionID WHEN 439 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS SpecimenHemolyedLipemicIctericName,
  CASE ProcessQuestionID WHEN 442 THEN Answer ELSE NULL END AS TimeFromCollectionToFreezingHours,
  CASE ProcessQuestionID WHEN 443 THEN Answer ELSE NULL END AS EquipmentFailureDeviationFromProtocol,
  CASE ProcessQuestionID WHEN 443 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS EquipmentFailureDeviationFromProtocolName,
  CASE ProcessQuestionID WHEN 450 THEN Answer ELSE NULL END AS VolumeRawUrineProcessed,
  CASE ProcessQuestionID WHEN 451 THEN Answer ELSE NULL END AS SpecimenInverted,
  CASE ProcessQuestionID WHEN 451 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS SpecimenInvertedName,
  CASE ProcessQuestionID WHEN 454 THEN Answer ELSE NULL END AS SpecimenProcessedWithin,
  CASE ProcessQuestionID WHEN 454 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS SpecimenProcessedWithinName,
  CASE ProcessQuestionID WHEN 455 THEN Answer ELSE NULL END AS TissuePosition,
  CASE ProcessQuestionID WHEN 455 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS TissuePositionName,
  CASE ProcessQuestionID WHEN 456 THEN Answer ELSE NULL END AS StorageTemperature,
  CASE ProcessQuestionID WHEN 456 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS StorageTemperatureName,
  CASE ProcessQuestionID WHEN 457 THEN Answer ELSE NULL END AS ProcessingMethod,
  CASE ProcessQuestionID WHEN 457 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS ProcessingMethodName,
  CASE ProcessQuestionID WHEN 458 THEN Answer ELSE NULL END AS PathologyDeptBlockNumber,
  CASE ProcessQuestionID WHEN 459 THEN Answer ELSE NULL END AS PrimaryTissueType,
  CASE ProcessQuestionID WHEN 459 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS PrimaryTissueTypeName,
  CASE ProcessQuestionID WHEN 460 THEN Answer ELSE NULL END AS SpecimenProcessedProtocol,
  CASE ProcessQuestionID WHEN 460 THEN (SELECT MEV.ValueName WHERE PQ.Answer=MEV.Value) ELSE NULL END AS SpecimenProcessedProtocolName
FROM	dbo.tblSpecimenBank195 AS PrimaryTbl 
		LEFT OUTER JOIN dbo.tblSpecimenBank195 AS SecondaryTbl ON PrimaryTbl.ParentSpecimenID = SecondaryTbl.SpecimenID 
		INNER JOIN NewCompass.dbo.tblSite AS s ON s.SiteID = 
			(CASE 
				WHEN LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 1) 
                      = '0' THEN substring((COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid)), 2, 2) 
                ELSE LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 3) 
             END) 
        LEFT OUTER JOIN tblLabs L on PrimaryTbl.LabID=L.LabID
        LEFT OUTER JOIN tblSpecimenPQ195 PQ ON PrimaryTbl.SpecimenID=PQ.SpecimenID
        INNER JOIN tblMetaElementValues MEV ON PQ.ProcessQuestionID=MEV.ElementID AND PQ.ProcessQuestionID NOT IN (431,442,450)

What am I doing wrong in my joins? I want to do a left outer join from tblSpecimenBank195 to tblSpecimenPQ195 on SpecimenID and then I want to join SpecimenPQ195 to tblMetaElementValues where ProcessQuestionID=ElementID UNLESS ProcessQuestionID=431,442 or 450

However, my query is returning MANY rows for each specimenid
 
my query is returning MANY rows for each specimenid

That's probably because there are several rows in tblMetaElementValues that match the join condition.

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
Can you try running this query?

Code:
SELECT	PrimaryTbl.SpecimenID, 
		COALESCE (SecondaryTbl.PptID, PrimaryTbl.PptID) AS pptid, 
		CASE 
			WHEN LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 1) = '0' 
			THEN substring((COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid)), 2, 2) 
			ELSE LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 3) 
			END AS CollectionSiteID, 
		s.Abbreviation AS CollectionSiteName, 
		CASE 
			WHEN PrimaryTbl.parentspecimenid = '' 
			THEN 'Parent' 
			ELSE 'Child' 
			END AS parentorchild, 
		PrimaryTbl.SpecimenSourceID,
		(SELECT     ValueName
			FROM          dbo.tblMetaElementValues
			WHERE      (ElementID = 8) AND (Active = '1') AND (Value = PrimaryTbl.SpecimenSourceID)) AS SpecimenSourceName, 
		PrimaryTbl.SpecimenStoredID,
		(SELECT     ValueName
			FROM          dbo.tblMetaElementValues AS tblMetaElementValues_18
			WHERE      (ElementID = 9) AND (Active = '1') AND (Value = PrimaryTbl.SpecimenStoredID)) AS SpecimenStoredName, 
			PrimaryTbl.Quantity, 
		CASE 
			WHEN PrimaryTbl.UnitID = 0 THEN 'unknown' 
			WHEN PrimaryTbl.UnitID = 1 THEN 'µl' 
			WHEN PrimaryTbl.UnitId = 2 THEN 'ml' 
		END AS Unit, 
		PrimaryTbl.CollectionDate, 
		PrimaryTbl.Comments, 
		PrimaryTbl.ParentSpecimenID, 
		CASE 
			WHEN PrimaryTbl.PptVisitType = 0 
			THEN SecondaryTbl.PptVisitType 
			ELSE PrimaryTbl.PptVisitType 
			END AS PptVisitType,
		(SELECT     ValueName
			FROM          dbo.tblMetaElementValues AS tblMetaElementValues_17
			WHERE      (ElementID = 82) AND (Active = '1') AND 
					(Value = CASE 
						WHEN PrimaryTbl.PptVisitType = 0 THEN SecondaryTbl.PptVisitType 
						ELSE PrimaryTbl.PptVisitType 
						END)) AS PptVisitTypeName, 
		PrimaryTbl.PptVisitDate, 
		PrimaryTbl.CurrentQuantity, 
		PrimaryTbl.CurrentQuantityUnitID,
		(SELECT     ValueName
			FROM          dbo.tblMetaElementValues AS tblMetaElementValues_16
			WHERE      (ElementID = 47) AND (Active = '1') AND (Value = PrimaryTbl.CurrentQuantityUnitID)) AS CurrentQuantityUnitName, 
		PrimaryTbl.Concentration, 
		PrimaryTbl.ConcentrationUnitID,
		(SELECT     ValueName
			FROM          dbo.tblMetaElementValues AS tblMetaElementValues_15
			WHERE      (ElementID = 42) AND (Active = '1') AND (Value = PrimaryTbl.ConcentrationUnitID)) AS ConcentrationUnitName, 
		PrimaryTbl.NumOfThawed, 
		L.SiteID AS StorageLabID,
		L.LabNameShort AS StorageLabName,
		PrimaryTbl.RefrigeratorID, 
		PrimaryTbl.BoxID, 
		PrimaryTbl.Row, 
		PrimaryTbl.Col, 
   
		--if specimenstoredid in 2,35,9, then fasting needs to be inherited from the parent
		Case
			WHEN PrimaryTbl.specimenstoredid in (2,9,35) THEN SecondaryTbl.Fasting
			ELSE PrimaryTbl.Fasting
			END AS Fasting,
		(SELECT     ValueName
			FROM          dbo.tblMetaElementValues AS tblMetaElementValues_14
			WHERE      (ElementID = 434) AND (Active = '1') AND (Value = Case
					WHEN PrimaryTbl.specimenstoredid in (2,9,35) THEN SecondaryTbl.Fasting
					ELSE PrimaryTbl.Fasting
					END)) AS FastingName, 
		PrimaryTbl.Status,
		(SELECT     ValueName
			FROM          dbo.tblMetaElementValues AS tblMetaElementValues_13
			WHERE      (ElementID = 29) AND (Active = '1') AND (Value = PrimaryTbl.Status)) AS StatusName, 
		PrimaryTbl.ReasonOfChange, 
		PrimaryTbl.ReasonOfDefective,
		(SELECT     ValueName
			FROM          dbo.tblMetaElementValues AS tblMetaElementValues_12
			WHERE      (ElementID = 61) AND (Active = '1') AND (Value = PrimaryTbl.ReasonOfDefective)) AS ReasonOfDefectiveName, 
		PrimaryTbl.OtherReasonOfDefective, 
		PrimaryTbl.TubeSize, 
		PrimaryTbl.MainSelected,
  
		Answers.SpecimensFrozenAtMinus70OrColder,
		AnswerNames.SpecimensFrozenAtMinus70OrColderName,
		Answers.PQComments,
		Answers.SpecimenPlacedImmedOnIceOrAt4Celsius,
  		AnswerNames.SpecimenPlacedImmedOnIceOrAt4CelsiusName,
  		Answers.FreezerNumberSpecimenStoredAt,
		Answers.SpecimenHemolyedLipemicIcteric,
		AnswerNames.SpecimenHemolyedLipemicIctericName,
		Answers.TimeFromCollectionToFreezingHours,
		Answers.EquipmentFailureDeviationFromProtocol,
		AnswerNames.EquipmentFailureDeviationFromProtocolName,
		Answers.VolumeRawUrineProcessed,
		Answers.SpecimenInverted,
		AnswerNames.SpecimenInvertedName,
		Answers.SpecimenProcessedWithin,
		AnswerNames.SpecimenProcessedWithinName,
		Answers.TissuePosition,
		AnswerNames.TissuePositionName,
		Answers.StorageTemperature,
		AnswerNames.StorageTemperatureName,
		Answers.ProcessingMethod,
		AnswerNames.ProcessingMethodName,
		Answers.PathologyDeptBlockNumber,
		Answers.PrimaryTissueType,
		AnswerNames.PrimaryTissueTypeName,
		Answers.SpecimenProcessedProtocol,
		AnswerNames.SpecimenProcessedProtocolName
FROM    dbo.tblSpecimenBank195 AS PrimaryTbl 
        INNER JOIN (
			Select	SpecimenId,
					Max(Case When ProcessQuestionID = 422 Then Answer End) AS SpecimensFrozenAtMinus70OrColder,
					Max(Case When ProcessQuestionID = 431 Then Answer End) AS PQComments,
					Max(Case When ProcessQuestionID = 435 Then Answer End) AS SpecimenPlacedImmedOnIceOrAt4Celsius,
					Max(Case When ProcessQuestionID = 438 Then Answer End) AS FreezerNumberSpecimenStoredAt,
					Max(Case When ProcessQuestionID = 439 Then Answer End) AS SpecimenHemolyedLipemicIcteric,
					Max(Case When ProcessQuestionID = 442 Then Answer End) AS TimeFromCollectionToFreezingHours,
					Max(Case When ProcessQuestionID = 443 Then Answer End) AS EquipmentFailureDeviationFromProtocol,
					Max(Case When ProcessQuestionID = 450 Then Answer End) AS VolumeRawUrineProcessed,
					Max(Case When ProcessQuestionID = 451 Then Answer End) AS SpecimenInverted,
					Max(Case When ProcessQuestionID = 454 Then Answer End) AS SpecimenProcessedWithin,
					Max(Case When ProcessQuestionID = 455 Then Answer End) AS TissuePosition,
					Max(Case When ProcessQuestionID = 456 Then Answer End) AS StorageTemperature,
					Max(Case When ProcessQuestionID = 457 Then Answer End) AS ProcessingMethod,
					Max(Case When ProcessQuestionID = 458 Then Answer End) AS PathologyDeptBlockNumber,
					Max(Case When ProcessQuestionID = 459 Then Answer End) AS PrimaryTissueType,
					Max(Case When ProcessQuestionID = 460 Then Answer End) As SpecimenProcessedProtocol
			From    dbo.tblSpecimenPQ195
			Where   ProcessQuestionID In (422,431,435,438,439,442,443,450,451,454,455,456,457,458,459,460)
			Group By SpecimenId
        ) As Answers
			On PrimaryTbl.SpecimenId = Answer.SpecimenId
		INNER JOIN (
			SELECT	tblSpecimenPQ195.SpecimenId,
					Max(Case When ProcessQuestionID = 422 Then ValueName End) AS SpecimensFrozenAtMinus70OrColderName,
					Max(Case When ProcessQuestionID = 435 Then ValueName End) AS SpecimenPlacedImmedOnIceOrAt4CelsiusName,
					Max(Case When ProcessQuestionID = 439 Then ValueName End) AS SpecimenHemolyedLipemicIctericName,
					Max(Case When ProcessQuestionID = 443 Then ValueName End) AS EquipmentFailureDeviationFromProtocolName,
					Max(Case When ProcessQuestionID = 451 Then ValueName End) AS SpecimenInvertedName,
					Max(Case When ProcessQuestionID = 454 Then ValueName End) AS SpecimenProcessedWithinName,
					Max(Case When ProcessQuestionID = 455 Then ValueName End) AS TissuePositionName,
					Max(Case When ProcessQuestionID = 456 Then ValueName End) AS StorageTemperatureName,
					Max(Case When ProcessQuestionID = 457 Then ValueName End) AS ProcessingMethodName,
					Max(Case When ProcessQuestionID = 459 Then ValueName End) AS PrimaryTissueTypeName,
					Max(Case When ProcessQuestionID = 460 Then ValueName End) AS SpecimenProcessedProtocolName
			FROM	dbo.tblMetaElementValues
					Inner Join dbo.tblSpecimenPQ195
						On tblMetaElementValues.ElementId = tblSpecimenPQ195.ProcessQuestionId
						And tblMetaElementValues.Value = tblSpecimenPQ195.Answer
			WHERE	dbo.tblSpecimenPQ195.ProcessQuestionId In (422,435,439,443,451,454,455,456,457,459,460)
			Group By tblSpecimenPQ195.SpecimenId 		
			) As AnswerNames
			On PrimaryTbl.SpecimenId = AnswerNames.SpecimenId
        LEFT OUTER JOIN dbo.tblSpecimenBank195 AS SecondaryTbl 
			ON PrimaryTbl.ParentSpecimenID = SecondaryTbl.SpecimenID 
        INNER JOIN NewCompass.dbo.tblSite AS s 
			ON s.SiteID = 
				(CASE 
					WHEN LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 1) 
						  = '0' THEN substring((COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid)), 2, 2) 
					ELSE LEFT(COALESCE (SecondaryTbl.pptid, PrimaryTbl.pptid), 3) 
				END) LEFT JOIN tblLabs L on PrimaryTbl.LabID=L.LabID


-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
That query took 0:25, but it is missing rows. I will take a look and try to understand to see if I can find the missing data.
 
I changed the two inner joins to tblSPecimenPQ195 to Left Outer Joins and got my missing data AND dropped the execution time down to 0:09. Now, why did that make such a difference?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top