using distinct in select having joins with multiple table - sql-server

Trying to use Distinct in select statement but not getting the desired result. I want CaseID to be returned for the last updated comment only. Below is the query that I am trying to use.
Select Distinct av.CaseID,fr.Rule_Description, av.Date, av.Status, fr.RULE_PRIORITY, ac.User_comments, max(ac.Comment_PostDate),ac.UserID
From tblAlertView av
Join tblAlertComment ac
on av.CaseID = ac.CaseID
Join tblFBLRule fr
on av.RuleID = fr.Rule_ID
Join TBLUSER usr
on ac.UserID = usr.USERID
group by av.CaseID, fr.Rule_Description, av.Date, av.Status, fr.RULE_PRIORITY, ac.User_comments, ac.Comment_PostDate,ac.UserID
Query Result

Remove
ac.Comment_PostDate
from group by clause

Rather than using JOIN to get to tblAlertComment, if you use CROSS APPLY you can specify to just return the top 1 comment per case:
SELECT av.CaseID,
fr.Rule_Description,
av.Date,
av.Status,
fr.RULE_PRIORITY,
ac.User_comments,
ac.Comment_PostDate,
ac.UserID
FROM tblAlertView AS av
INNER JOIN tblFBLRule AS fr
ON av.RuleID = fr.Rule_ID
CROSS APPLY
( SELECT TOP 1 ac.User_comments, ac.Comment_PostDate, ac.UserID
FROM tblAlertComment AS ac
INNER JOIN tblUser AS usr
ON usr.UserID = ac.UserID
WHERE ac.CaseID = av.CaseID
ORDER BY ac.Comment_PostDate DESC
) AS ac;

Related

Filtering date after max date SQL

I have a table with values en date/timstamps. This table is dbo.meterdata.value. The output that i want to see is as followed: The latest date/timestamp (Max) but only the ones where te latest date/timestamp is last week. My Query is:
SELECT dbo.meter.DataImportCode
,dbo.meter.NAME
,dbo.company.NAME
,dbo.meter.MeterNumber
,MAX(dbo.meterdata.RoundedTimeStamp) AS 'laatste datum'
,dbo.MeterOperator.Description
,dbo.meter.CumulativeReadings
FROM dbo.meter
LEFT OUTER JOIN DBO.MeterData ON dbo.meter.MeterID = dbo.meterdata.MeterID
JOIN DBO.Site ON dbo.meter.SiteID = dbo.site.SiteID
JOIN DBO.Company ON dbo.site.CompanyID = dbo.company.CompanyID
JOIN DBO.MeterOperator ON dbo.meter.MeterOperatorID = dbo.MeterOperator.MeterOperatorID
--WHERE (select (dbo.meterdata.roundedtimestamp) from dbo.MeterData) < DateAdd(DD,-7,GETDATE() )
AND dbo.meterdata.RoundedTimeStamp IS NOT NULL
GROUP BY dbo.meter.DataImportCode
,dbo.company.NAME
,dbo.meter.NAME
,dbo.meter.MeterNumber
,dbo.MeterOperator.Description
,dbo.meter.CumulativeReadings
Example of the unfilterd result:
Example
Thank you for help and support
Try the following:
select dbo.meter.DataImportCode, dbo.meter.Name, dbo.company.Name, dbo.meter.MeterNumber,MAX(dbo.meterdata.RoundedTimeStamp) AS 'laatste datum', dbo.MeterOperator.Description, dbo.meter.CumulativeReadings
from dbo.meter
LEFT OUTER JOIN DBO.MeterData ON dbo.meter.MeterID = dbo.meterdata.MeterID
JOIN DBO.Site on dbo.meter.SiteID = dbo.site.SiteID
JOIN DBO.Company on dbo.site.CompanyID = dbo.company.CompanyID
JOIN DBO.MeterOperator on dbo.meter.MeterOperatorID = dbo.MeterOperator.MeterOperatorID
--WHERE (select (dbo.meterdata.roundedtimestamp) from dbo.MeterData) < DateAdd(DD,-7,GETDATE() )
--AND dbo.meterdata.RoundedTimeStamp is not null
GROUP BY dbo.meter.DataImportCode, dbo.company.name, dbo.meter.Name, dbo.meter.MeterNumber, dbo.MeterOperator.Description, dbo.meter.CumulativeReadings
HAVING [laatste datum] < DateAdd(day,-7,GETDATE())
If I understood you right, what you want to do is filter out the data after it has been grouped. This is done using the HAVING clause of the SELECT statement, as the above query depicts.

Make one-to-one relation between two tables that have one-to-many relation in SQL

I have these queries :
SELECT
dbo.Lines.Unit, dbo.Lines.LineNumber, dbo.Lines.DocumentNumber,
dbo.BaseMaterials.Name AS MaterialName,
dbo.MaterialDescriptions.Name AS MaterialDescription,
dbo.MaterialDescriptions.Description,
dbo.MaterialScopes.ScopeName, dbo.MaterialScopeObjectNames.ObjectName,
dbo.MaterialDescriptions.Size1, dbo.MaterialDescriptions.Size2,
dbo.MaterialDescriptions.ItemCode, dbo.Materials.Quantity,
dbo.Materials.Discipline, dbo.Materials.Id, dbo.Lines.Id AS LineId
FROM
dbo.Materials
INNER JOIN
dbo.Lines ON dbo.Materials.LineId = dbo.Lines.Id
INNER JOIN
dbo.BaseMaterials ON dbo.Lines.BaseMaterialId = dbo.BaseMaterials.Id
INNER JOIN
dbo.MaterialDescriptions ON dbo.Materials.MaterialDescriptionId = dbo.MaterialDescriptions.Id
INNER JOIN
dbo.MaterialScopes ON dbo.MaterialDescriptions.MaterialScopeId = dbo.MaterialScopes.Id
INNER JOIN
dbo.MaterialScopeObjectNames ON dbo.MaterialDescriptions.MaterialScopeObjectId = dbo.MaterialScopeObjectNames.Id
It returns 16000 records. I have another tables with joints name that has a relation with material table on lineId every material can have multi joints so my query when I add joints table is like this :
SELECT
dbo.Lines.Unit, dbo.Lines.LineNumber, dbo.Lines.DocumentNumber,
dbo.BaseMaterials.Name AS MaterialName,
dbo.MaterialDescriptions.Name AS MaterialDescription,
dbo.MaterialDescriptions.Description, dbo.MaterialScopes.ScopeName,
dbo.MaterialScopeObjectNames.ObjectName, dbo.MaterialDescriptions.Size1,
dbo.MaterialDescriptions.Size2, dbo.MaterialDescriptions.ItemCode,
dbo.Materials.Quantity, dbo.Materials.Discipline, dbo.Materials.Id,
dbo.Lines.Id AS LineId, dbo.Joints.TestPackageId
FROM
dbo.Materials
INNER JOIN
dbo.Lines ON dbo.Materials.LineId = dbo.Lines.Id
INNER JOIN
dbo.BaseMaterials ON dbo.Lines.BaseMaterialId = dbo.BaseMaterials.Id
INNER JOIN
dbo.MaterialDescriptions ON dbo.Materials.MaterialDescriptionId = dbo.MaterialDescriptions.Id
INNER JOIN
dbo.MaterialScopes ON dbo.MaterialDescriptions.MaterialScopeId = dbo.MaterialScopes.Id
INNER JOIN
dbo.MaterialScopeObjectNames ON dbo.MaterialDescriptions.MaterialScopeObjectId = dbo.MaterialScopeObjectNames.Id
INNER JOIN
dbo.Joints ON dbo.Materials.LineId = dbo.Joints.LineId
As you can see in the last line i make a join between joints and materials to access the testpackageid column in joints table .but my result returns 220000records .How can i change the join type i mean left or right to just returns 16000 records with its testpackageId
You can't using JOIN. However, you can using CROSS APPLY:
FROM . . .
dbo.MaterialScopeObjectNames
ON dbo.MaterialDescriptions.MaterialScopeObjectId = dbo.MaterialScopeObjectNames.Id CROSS APPLY
(SELECT TOP 1 j.*
FROM dbo.Joints j
WHERE dbo.Materials.LineId = j.LineId
) J
Normally, you would include an ORDER BY when using TOP so you have some control over the row being returned.
Also note that the use of table aliases makes the query easier to write and to read.
You can get it very easily with just a subquery. Leave your query as it is, and add a subquery to get that information from Joints.
SELECT dbo.Lines.Unit, dbo.Lines.LineNumber, dbo.Lines.DocumentNumber, dbo.BaseMaterials.Name AS MaterialName, dbo.MaterialDescriptions.Name AS MaterialDescription, dbo.MaterialDescriptions.Description,
dbo.MaterialScopes.ScopeName, dbo.MaterialScopeObjectNames.ObjectName, dbo.MaterialDescriptions.Size1, dbo.MaterialDescriptions.Size2, dbo.MaterialDescriptions.ItemCode, dbo.Materials.Quantity,
dbo.Materials.Discipline, dbo.Materials.Id, dbo.Lines.Id AS LineId,
(select top 1 dbo.Joints.TestPackageId from dbo.Joints where dbo.Joints.LineId = dbo.Materials.LineId)
FROM dbo.Materials INNER JOIN
dbo.Lines ON dbo.Materials.LineId = dbo.Lines.Id INNER JOIN
dbo.BaseMaterials ON dbo.Lines.BaseMaterialId = dbo.BaseMaterials.Id INNER JOIN
dbo.MaterialDescriptions ON dbo.Materials.MaterialDescriptionId = dbo.MaterialDescriptions.Id INNER JOIN
dbo.MaterialScopes ON dbo.MaterialDescriptions.MaterialScopeId = dbo.MaterialScopes.Id INNER JOIN
dbo.MaterialScopeObjectNames ON dbo.MaterialDescriptions.MaterialScopeObjectId = dbo.MaterialScopeObjectNames.Id

how to use this without subquery. I need to use with join to get same result set

How to use this below query as join instead of subquery. It's resulting poor performance
SELECT EBIJ.* FROM BUDLINEITEMS EBIJ
WHERE ReferenceId NOT IN (SELECT ImportKeyId FROM External_Blk_Itm_JounalEntries)
SELECT EBIJ.*
FROM BUDLINEITEMS EBIJ
LEFT JOIN External_Blk_Itm_JounalEntries E
ON EBIJ.ReferenceId = E.ImportKeyId
WHERE E.ImportKeyId IS NULL
OR
SELECT EBIJ.* FROM BUDLINEITEMS EBIJ
WHERE NOT EXISTS (SELECT 1
FROM External_Blk_Itm_JounalEntries E
WHERE EBIJ.ReferenceId = E.ImportKeyId )

TSQL Inner select using outer join

I have a query that is working for the most part until I had to add the inner select for "Trainers".
As you can see in the code below, I am trying to get all of the trainers for each of the segment ID's.
I am getting an error on the first inner selects where clause WHERE trn.segmentID = tes.teSegmentID saying that tes.teSegmentID is not defined.
Is there another way to approach this query in order to get the trainers like I am trying to accomplish?
SELECT *,
(SELECT e2.[FirstName] AS trainerFirst,
e2.[LastName] AS trainerLast
FROM BS_Training_Trainers AS trn
LEFT OUTER JOIN
employeeTable AS e2
ON trn.trainerEmpID = e2.EmpID
WHERE trn.segmentID = tes.teSegmentID
FOR XML PATH ('trainer'), TYPE, ELEMENTS, ROOT ('trainers'))
FROM dbo.BS_TrainingEvents AS a
WHERE a.trainingEventID IN (SELECT tes.trainingEventID
FROM dbo.BS_TrainingEvent_Segments AS tes
INNER JOIN
dbo.BS_TrainingEvent_SegmentDetails AS tesd
ON tesd.segmentID = tes.teSegmentID
INNER JOIN
dbo.BS_LocaleCodes AS locale
ON locale.localeID = tesd.localeID
WHERE locale.location = 'Baltimore');
It seems like you're taking the scenic route towards this:
SELECT a.*,
X.[FirstName],
X.[LastName]
FROM dbo.BS_TrainingEvents AS a
LEFT OUTER JOIN (SELECT e2.[FirstName], e2.[LastName], locale.location FROM dbo.BS_TrainingEvent_Segments AS tes
INNER JOIN dbo.BS_Training_Trainers AS trn ON trn.segmentID = tes.teSegmentID
INNER JOIN dbo.BS_TrainingEvent_SegmentDetails AS tesd ON tesd.segmentID = tes.teSegmentID
INNER JOIN dbo.BS_LocaleCodes AS locale ON locale.localeID = tesd.localeID
LEFT OUTER JOIN employeeTable AS e2 ON trn.trainerEmpID = e2.EmpID) AS X ON a.trainingEventID = X.trainingEventID
WHERE X.location = 'Baltimore';
Not sure if I got all those joins right, it was hard to decode from all the nesting you have going on.
If I have guessed table relationships from their names correctly, the only way to solve this is to reference the same filtering condition twice: first, in the XML generation part, and second in the outer level of the query:
with cte as (
select distinct tes.trainingEventID, tes.teSegmentID
from dbo.BS_TrainingEvent_Segments AS tes
INNER JOIN dbo.BS_TrainingEvent_SegmentDetails AS tesd ON tesd.segmentID = tes.teSegmentID
INNER JOIN dbo.BS_LocaleCodes AS locale ON locale.localeID = tesd.localeID
WHERE locale.location = 'Baltimore'
)
SELECT a.*, (
SELECT e2.[FirstName] AS trainerFirst, e2.[LastName] AS trainerLast
FROM BS_Training_Trainers AS trn
LEFT OUTER JOIN employeeTable AS e2 ON trn.trainerEmpID = e2.EmpID
inner join cte c on trn.segmentID = c.teSegmentID
FOR XML PATH ('trainer'), TYPE, ELEMENTS, ROOT ('trainers')
)
FROM dbo.BS_TrainingEvents AS a
where exists (select 0 from cte c where c.testrainingEventID = a.trainingEventID);
It's difficult to tell whether this is completely correct, of course, but I hope you get the idea.
Oh yes, and if you would have an event with multiple Baltimore segments, you will never be able to tell which trainer takes which one. But you can always add more data into XML to resolve this.

WHERE condition based in the count row in another query

I am trying to make a query using a condition based in the amont of rows obtained in another query. But I cannot get the correct way. Does any body can help me ? What I am trying to do is :
SELECT ChildDummyTable.Id ChildDummyTableId,
ParentDummyTable.Id ParentDummyTableId
FROM [DummyTable] ChildDummyTable
INNER JOIN [DummyTable] ParentDummyTable
ON ParentDummyTable.Id = ChildDummyTable.ParentDummyRowId
where (SELECT DummyRow2 FROM DummyTable2 WHERE DummyTableId=ChildDummyTable.Id
except SELECT DummyRow2 FROM DummyTable2 ParentDummyTable2
WHERE ParentDummyTable2.DummyTableId=DummyTable.Id).COUNT(DummyRow2)>0
You can use EXISTS:
SELECT ChildDummyTable.Id ChildDummyTableId,
ParentDummyTable.Id ParentDummyTableId
FROM [DummyTable] ChildDummyTable
INNER JOIN [DummyTable] ParentDummyTable
ON ParentDummyTable.Id = ChildDummyTable.ParentDummyRowId
WHERE EXISTS(SELECT DummyRow2 FROM DummyTable2
WHERE DummyTableId=ChildDummyTable.Id
EXCEPT
SELECT DummyRow2 FROM DummyTable2 ParentDummyTable2
WHERE ParentDummyTable2.DummyTableId=DummyTable.Id)
with a as
(SELECT ChildDummyTable.Id ChildDummyTableId
,ParentDummyTable.Id ParentDummyTableId
,ROW_NUMBER() OVER(PARTITION by
ChildDummyTable.Id ChildDummyTableId
,ParentDummyTable.Id ParentDummyTableId
)
aS duplicateRecCount
FROM [DummyTable] ChildDummyTable
INNER JOIN [DummyTable] ParentDummyTable
ON ParentDummyTable.Id = ChildDummyTable.ParentDummyRowId
)
Select * from a
where duplicateRecCount > 1

Resources