Select Newest Record - sql-server

I have two tables (Journal and Incident). Each incident may have more than one journal entry. I want to select the record and the most recent journal data.
The where section at the bottom is what filters the incidents I want to see. Of those, I want the journal values associated with the most recent journal entry.
This is an amalgam of code I've found on here, but when I run it I get a "Query execution failed for dataset 'DataSet1'. Unfortunately, I don't have access to the log files to see if there are clues there.
Any help is appreciated. I think I may have it nested wrong.
SELECT
b.IncidentNumber
,a.Subject
,a.CreatedDateTime
,b.SubCategory
,b.EffectiveDueDate
,b.NextActionDate
,b.ProfileFullName
FROM
(
SELECT
b.IncidentNumber
,a.Subject
,a.CreatedDateTime
,rn = row_number() OVER (PARTITION by b.IncidentNumber ORDER BY
a.CreatedDateTime DESC)
,b.SubCategory
,b.EffectiveDate
,b.NextActionDate
,b.ProfileFullName
FROM
Journal a LEFT JOIN Incident b ON
a.ParentRecordNumber = b.IncidentNumber
WHERE a.Category LIKE '%KANBAN%'
AND (b.Status LIKE' %Waiting%' OR b.status LIKE '%Active%')
AND b.SubCategory <> 'User Termination'
AND b.SubCategory <> 'Res Temp Termination'
AND a.Subject LIKE 'UP |%'
) X
WHERE rn = 1

Few things:
Outer most selected values should be from inline view aliased "X" No a. or b. as those alias only are in scope to the in inner query. (except when using coorlation but that's 1 level only I believe)
You either need to right join instead of left or change the order of the tables. I believe you want all incidents and the MOST recent Journal; not all journals and the related incident if one exists. thus I changed the order.
Lastly when using outer joins, you can only put limits on the all records table of the outer join. Where clause criteria the OUTER joined tables will cause the null records generated by the outer join to be excluded. To resolve this you must move the limiting criteria to the join or use an 'or' statement to check for null (it's cleaner to move it to the join). Think of it is applying the limit before the join occurs so Null records from incident are kept. otherwise the outer join simulates a INNER JOIN by excluding those records not in both tables (or in this case in incident but not in journal)
.
SELECT x.IncidentNumber --alias x not a/b as the from is aliased as 'X'
, x.Subject
, x.CreatedDateTime
, x.SubCategory
, x.EffectiveDueDate
, x.NextActionDate
, x.ProfileFullName
FROM (SELECT b.IncidentNumber
, a.Subject
, a.CreatedDateTime
, rn = row_number() OVER (PARTITION by b.IncidentNumber
ORDER BY a.CreatedDateTime DESC)
, b.SubCategory
, b.EffectiveDate
, b.NextActionDate
, b.ProfileFullName
FROM Incident b --switched the order I think you want all incidents and if a journal exists it's value.
LEFT JOIN Journal a
ON a.ParentRecordNumber = b.IncidentNumber
-- Since A is on the if match found to B, we need to move this to the join or we lose the records created from the outer join.
AND a.Category LIKE '%KANBAN%'
AND a.Subject LIKE 'UP |%'
--moved some where clause criteria to the join Since B is on the "all records side" of the outer join we can leave B in the where clause.
WHERE (b.Status LIKE' %Waiting%' OR b.status LIKE '%Active%')
AND b.SubCategory <> 'User Termination'
AND b.SubCategory <> 'Res Temp Termination') X
WHERE rn = 1
If you are not getting records from here, then I'd start removing some of the limiting criteria to ensure the query is functioning as desired and then add back in limits to see what's causing no records to be found.

I've finally got this report working as expected. It took a few iterations to get the query working, but it's doing what it should, now. Many thanks for your assist. I would have never gotten there without it!
SELECT x.IncidentNumber
, x.Subject
, x.CreatedDateTime
, x.SubCategory
, x.ProfileFullName
, x.PropertyNumber
, x.Status
, x.EffectiveDueDate
FROM (SELECT b.IncidentNumber
, a.Subject
, a.CreatedDateTime
, rn = row_number() OVER (PARTITION by b.IncidentNumber
ORDER BY a.CreatedDateTime DESC)
, b.SubCategory
, b.ProfileFullName
, b.PropertyNumber
, b.Status
, b.EffectiveDueDate
FROM Incident b
RIGHT JOIN Journal a
ON a.ParentRecordNumber = b.IncidentNumber
AND a.Category LIKE '%KANBAN%'
AND a.Subject LIKE 'UP |%'
WHERE (b.Status LIKE' %Waiting%' OR b.status LIKE '%Active%')
) x
WHERE rn = 1

Related

Two IDs matching one causing duplicates

I am trying to inner join however I keep getting this duplicate pop up where there are two job IDs matching one Invoice ID (inner joined with a middle table that links both).
I want to only get 1 invoice id and summing the total despite 2 job ids matching it.
Basically there is AINVOICEID (table:Invoice ) matching ABINVOICEID (table:INLines) and inside the INLines table, it contains ARJOBID that matches the JOBID in Jobs.
Select distinct sum(totalBASE) as InvoiceTotal,
DATEADD(MONTH, DATEDIFF(MONTH, 0, InvDate), 0)
from (select distinct left(JOBID,5)as JOBID
from jobs
group by JOBID
) jobs
inner join (select distinct ABINVOICEID, left(ARLJOBID,5) as arljobid
from INLines
group by ARLJOBID, ABINVOICEID
) INLines
on left(ARLJOBID,5) = left(JOBID,5)
inner join (select distinct AINVOICEID
, sum(totalBASE) as totalBASE
, InvDate
from Invoice
group by AINVOICEID, InvDate
) Invoice
on AINVOICEID = ABINVOICEID
where left(JOBID ,5)=left(ARLJOBID,5) and AINVOICEID = ABINVOICEID
and InvDate between '05/01/2022' AND '05/31/2022'
group by left(JOBID ,5), DATEADD(MONTH, DATEDIFF(MONTH, 0, InvDate), 0)
It is quite difficult to try and make sense of what you're asking without an example of the output that you're getting and what the expected output is.
However, I think you're wanting something like this:
SELECT I.AINVOICEID, SUM(I.totalBASE) AS totalBASE, InvDate
FROM Invoice I INNER JOIN
(
SELECT L.ABINVOICEID, J.JOBID
FROM INLines L INNER JOIN
Jobs J ON L.ARLJOBID = J.JOBID
GROUP BY L.ABINVOICEID, J.JOBID
) LJ ON I.AINVOICEID = L.ABINVOICEID
WHERE I.InvDate BETWEEN '05/01/2022' AND '05/31/2022'
GROUP BY I.AINVOICEID, InvDate
This is based on what your SQL query which doesn't really look like it needs to JOIN on the INLines or Jobs table because you're getting everything you need from the Invoice table in the SELECT ?
If this isn't what you're after, if you can elaborate a bit more, then the community on here should be able to better assist with your question.

SQL CASE mixes up my grouping

The problem situates itself at the 4th line of the SELECT statement: CASE WHEN ct.TransactionReason=622 THEN ABS(ct.netquantity) ELSE c.RealNetWeight END AS NetWeight
When I add this line to the statement, my grouping will change. Instead of returning one line it now gives me back the amount of lines of different c.realnetweight.
Problem is that I only want to return one line. Sort of like a coalesce that when there is a ct.transactionreason = 622, it should give me ABS(ct.netquantity), otherwise the c.realnetweight. Code can be found beneath, suggestions would be very helpful. Thanks.
SELECT CASE WHEN P.Wrapped = 1 THEN T.[Level]+1 ELSE T.[Level] END AS [Level]
, #CoilId AS CoilId
, c.SupplierCoilID
, CASE WHEN ct.TransactionReason=622 THEN ABS(ct.netquantity) ELSE c.RealNetWeight END AS NetWeight
, C.RealGrossWeight
, p1.Description
, p1.product
, s.StackID
, s.ProductID
, s.Weight
, P.Product
, P.Description AS 'ProductDescription'
, COUNT(t.BlankId) AS 'NumberOfBlanks'
, c1.Description as 'Status'
, pv.ProductionWeight
, pv.BlankWeight
, t.BlankStatus
FROM #Trace T
INNER JOIN SKUTraceability SKUT ON SKUT.SKUID = T.SKUID
INNER JOIN Stack s ON SKUT.StackID = s.StackID
INNER JOIN Product p ON s.ProductID = p.ProductID
INNER JOIN Coil c ON c.CoilID=#CoilId
INNER JOIN CoilTransaction ct on ct.CoilID=#CoilId
INNER JOIN Product p1 ON c.ProductID=p1.ProductID
INNER JOIN Code c1 ON t.BlankStatus=c1.codenumber AND c1.codetypeid=17
INNER JOIN #ProductVersion pv ON pv.ProductID=p.ProductId AND s.ProductVersion = pv.ProductVersion
WHERE t.BlankId IS NOT NULL
GROUP BY T.[Level]
, c.SupplierCoilID
, CASE WHEN ct.TransactionReason=622 THEN ABS(ct.netquantity) ELSE c.RealNetWeight END
, c.RealGrossWeight
, p1.Description
, p1.product
, s.StackID
, s.ProductID
, s.Weight
, p.Product
, p.Description
, c1.Description
, pv.ProductionWeight
, pv.BlankWeight
, p.Wrapped
, t.BlankStatus
Hard to answer without understanding your table structures however, it appears that CoilTransaction is some sort of transaction table, i.e. a single product can have many transactions.
In your SELECT query, the line causing you issues, is the only line that references your CoilTransaction table therefore I believe, the reason you're returning multiple rows is because you're grouping on a value that is not unique. Also, are transactions individual items because you seem to have a quantity column on the table.
In short, you can't get the grouping you want by including those columns from your transaction table. You would need to elaborate more on what you're trying to accomplish for us to give a more suitable solution. What does that line mean?
For at least one CoilID in table Coil, you will have more than one value in the field netquantity in the table CoilTransaction. This is what is causing the increase in the number of records returned when you include this field in your CASE statement.
I would recommend finding the netquantity value that you want from CoilTransaction in a CTE, and then bringing this in to your CASE statement. For example:
;WITH transaction_summary AS (
SELECT
ct.CoilID,
ct.TransactionReason,
MAX(ct.netquantity) -- choose your aggregate function here
FROM
CoilTransaction ct
GROUP BY
ct.CoilID,
ct.TransactionReason
)
...

T-SQL: Ugly SQL

EDIT: Just so folks understand, I'm not worried about the formatting, I'm worried about the usage of the GROUP By and the usage of the aggregate fields when it doesn't make a whole lot of sense.
I've been tasked with making some SQL more readable. While I generally know what to do, this particular query escapes me. The gist of the query involves the writer grouping by a whole bunch of fields, and adding those fields to the query results. For fields that he/she doesn't GROUP BY, they use a MIN aggregate function I guess to "make the error go away"
MIN(ISNULL(dbo.V_CONNECT_ContactPartnerDetail_0010.SAPNr, N'')) AS sapkunr,
My difficulty comes from the fact that I can stuff the GROUP BY into a CTE, and then branch out from there, but I've never gotten the row counts to match up between the query I've created and the original one. Any help on making this SQL more readable and making its intent more clear (no functions to make the error go away) would be greatly appreciated.
SELECT dbo.V_CONNECT_ContactPartnerDetail_0010.ID_FI AS firmencode,
dbo.V_CONNECT_ContactPartnerDetail_0010.ID_KP AS partnercode,
dbo.V_CONNECT_ContactPartnerDetail_0010.Nachname,
Min(Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.Vorname, '')) AS vname,
Min(CASE V_CONNECT_ContactPartnerDetail_0010.Anrede
WHEN 'Frau' THEN 2
ELSE 1
END) AS anrede,
Min(Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.EMail, N'')) AS mail,
Min(Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.SAPNr, N'')) AS sapkunr,
Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.Titel, N'') AS titel
FROM dbo.V_CONNECT_ContactPartnerDetail_0010
INNER JOIN dbo.V_CONNECT_ContactPartnerPivot
ON dbo.V_CONNECT_ContactPartnerDetail_0010.ID_C005 = dbo.V_CONNECT_ContactPartnerPivot.ID_C005
LEFT OUTER JOIN dbo.V_CONNECT_Firmen_PZ_Download
ON dbo.V_CONNECT_ContactPartnerDetail_0010.ID_VF = dbo.V_CONNECT_Firmen_PZ_Download.ID_VF
WHERE ( dbo.V_CONNECT_ContactPartnerDetail_0010.VKO = '0010' )
GROUP BY dbo.V_CONNECT_ContactPartnerDetail_0010.ID_FI,
dbo.V_CONNECT_ContactPartnerDetail_0010.ID_KP,
dbo.V_CONNECT_ContactPartnerDetail_0010.Nachname,
dbo.V_CONNECT_ContactPartnerDetail_0010.Ort,
dbo.V_CONNECT_ContactPartnerPivot.flg_spl,
dbo.V_CONNECT_ContactPartnerPivot.flg_ha,
dbo.V_CONNECT_ContactPartnerPivot.flg_fu,
dbo.V_CONNECT_ContactPartnerPivot.flg_ma,
dbo.V_CONNECT_ContactPartnerPivot.flg_ph,
Isnull(dbo.V_CONNECT_ContactPartnerDetail_0010.Titel, N'')
This is much more "readable" to me
SELECT cpd.ID_FI AS firmencode
, cpd.ID_KP AS partnercode
, cpd.Nachname AS Nachname
, MIN(ISNULL( cpd.Vorname ,'')) AS vname
, MIN(CASE cpd.Anrede WHEN 'Frau' THEN 2 ELSE 1 END) AS anrede
, MIN(ISNULL( cpd.EMail ,N'')) AS mail
, MIN(ISNULL( cpd.SAPNr ,N'')) AS sapkunr
, ISNULL( cpd.Titel ,N'') AS titel
FROM dbo.V_CONNECT_ContactPartnerDetail_0010 cpd
JOIN dbo.V_CONNECT_ContactPartnerPivot cpp
ON cpd.ID_C005 = cpp.ID_C005
LEFT
JOIN dbo.V_CONNECT_Firmen_PZ_Download fpd
ON fpd.ID_VF = cpd.ID_VF
WHERE cpd.VKO = '0010'
GROUP
BY cpd.ID_FI
, cpd.ID_KP
, cpd.Nachname
, cpd.Ort
, cpp.flg_spl
, cpp.flg_ha
, cpp.flg_fu
, cpp.flg_ma
, cpp.flg_ph
, ISNULL(cpd.Titel ,N'')
EDIT
If I was "tasked with making some SQL more readable", I'd start with the changes above.
Beyond that, it's not clear why the GROUP BY clause includes expression that aren't in the SELECT list. It's valid to do that. But what's curious is that uf there are multiple rows from "cpd" that have different values of "Ort", then there's a pontential to get multiple rows returned, with the same values of "ID_FI", "ID_KP", "Nachname".
What really sticks out though is the outer join to "fpd", and apart from the reference to the "ID_VF" column in the join condition, there aren't any references to columns from "fpd" anywhere else in the query. It seems like if that outer join were removed, we'd get the same result.
The first structural change I would propose would be the removal of the join to "fpd".
SELECT cpd.ID_FI AS firmencode
, cpd.ID_KP AS partnercode
, cpd.Nachname AS Nachname
, MIN(ISNULL( cpd.Vorname ,'')) AS vname
, MIN(CASE cpd.Anrede WHEN 'Frau' THEN 2 ELSE 1 END) AS anrede
, MIN(ISNULL( cpd.EMail ,N'')) AS mail
, MIN(ISNULL( cpd.SAPNr ,N'')) AS sapkunr
, ISNULL( cpd.Titel ,N'') AS titel
FROM dbo.V_CONNECT_ContactPartnerDetail_0010 cpd
JOIN dbo.V_CONNECT_ContactPartnerPivot cpp
ON cpp.ID_C005 = cpd.ID_C005
WHERE cpd.VKO = '0010'
GROUP
BY cpd.ID_FI
, cpd.ID_KP
, cpd.Nachname
, cpd.Ort
, ISNULL( cpd.Titel ,N'')
, cpp.flg_spl
, cpp.flg_ha
, cpp.flg_fu
, cpp.flg_ma
, cpp.flg_ph
We can rearrange the expression in the GROUP BY clause, to move "Title" up with the other columns from "cpd". Without an ORDER BY clause, there's no guarantee what order the rows will be returned in.
We can't tell (from the query, and from the information provided) whether the "ID_C005" column is the PRIMARY KEY or a UNIQUE KEY in either "cpd" or "cpp".
And not knowing that, we can't really make other change to the query without potentially changing the result. If "ID_C005" is unique in "cpp", then we could eliminate all of the "cpp" column references from the GROUP BY.
If the purpose of the inner join (to "cpp") is to filter out rows from "cpd" that don't have a matching row in "cpp", we could make some other changes to the query. And that might make it more "readable".

SELECT Specefic Date in Tsql Query?

I have 3 tables that are joined together with this query.
One of them brings me people names , another one brings me their points and the last one brings me date time.
I select the total people score.
Also, there is a column in the 3th tables that brings me the scores' transaction Date Time. My problem is that I want to write a TSQL query with this condition:
Select the transaction date where the people score is 12,000 or more.
In my idea I should use while loop but I do not know the syntax?
This is how I would do it-
SELECT cp.FirstName
, cp.LastName
, SUM(Points) as Score
FROM ClubProfile cp
RIGHT JOIN CardTransaction ct
ON cp.ClubProfileId = ct.ClubProfileId
INNER JOIN Your3rdTable as t3
ON cp.ClubProfileId = t3.ClubProfileId
WHERE CONVERT(VARCHAR, ct.[Date Column], 101) = #your_date_param
GROUP BY
cp.FirstName
, cp.LastName
HAVING SUM(Points) >=12000
Based on your post this should be close to what you need. You need to add that 3rd table and alter this statement accordingly.
SELECT cp.FirstName
, cp.LastName
, SUM(Points) as Score
FROM [fidilio].[dbo].[ClubProfile] cp
RIGHT JOIN (
CardTransaction ct
INNER JOIN CardTransactionLog ctl
ON cp.CardTransactionLogId = ctl.CardTransactionLogId
)
ON cp.ClubProfileId = ct.ClubProfileId
GROUP BY
cp.FirstName
, cp.LastName
HAVING SUM(Points) >=12000
AND ctl.TransactionTimeStamp = #SomeDateTimeVariable
The variable #SomeDateTimeVariable has to come from someplace what is your exact time-frame criteria

Join subquery with min

I'm pulling my hair out over a subquery that I'm using to avoid about 100 duplicates (out of about 40k records). The records that are duplicated are showing up because they have 2 dates in h2.datecreated for a valid reason, so I can't just scrub the data.
I'm trying to get only the earliest date to return. The first subquery (that starts with "select distinct address_id", with the MIN) works fine on it's own...no duplicates are returned. So it would seem that the left join (or just plain join...I've tried that too) couldn't possibly see the second h2.datecreated, since it doesn't even show up in the subquery. But when I run the whole query, it's returning 2 values for some ipc.mfgid's, one with the h2.datecreated that I want, and the other one that I don't want.
I know it's got to be something really simple, or something that just isn't possible. It really seems like it should work! This is MSSQL. Thanks!
select distinct ipc.mfgid as IPC, h2.datecreated,
case when ad.Address is null
then ad.buildingname end as Address, cast(trace.name as varchar)
+ '-' + cast(trace.Number as varchar) as ONT,
c.ACCOUNT_Id,
case when h.datecreated is not null then h.datecreated
else h2.datecreated end as Install
from equipmentjoin as ipc
left join historyjoin as h on ipc.id = h.EQUIPMENT_Id
and h.type like 'add'
left join circuitjoin as c on ipc.ADDRESS_Id = c.ADDRESS_Id
and c.GRADE_Code like '%hpna%'
join (select distinct address_id, equipment_id,
min(datecreated) as datecreated, comment
from history where comment like 'MAC: 5%' group by equipment_id, address_id, comment)
as h2 on c.address_id = h2.address_id
left join (select car.id, infport.name, carport.number, car.PCIRCUITGROUP_Id
from circuit as car (NOLOCK)
join port as carport (NOLOCK) on car.id = carport.CIRCUIT_Id
and carport.name like 'lead%'
and car.GRADE_Id = 29
join circuit as inf (NOLOCK) on car.CCIRCUITGROUP_Id = inf.PCIRCUITGROUP_Id
join port as infport (NOLOCK) on inf.id = infport.CIRCUIT_Id
and infport.name like '%olt%' )
as trace on c.ccircuitgroup_id = trace.pcircuitgroup_id
join addressjoin as ad (NOLOCK) on ipc.address_id = ad.id
The typical approach to only getting the lowest row is one of the following. You didn't bother to specify what version of SQL Server you're using, what you want to do with ties, and I have little interest to try to work this into your complex query, so I'll show you an abstract simplification for different versions.
SQL Server 2000
SELECT x.grouping_column, x.min_column, x.other_columns ...
FROM dbo.foo AS x
INNER JOIN
(
SELECT grouping_column, min_column = MIN(min_column)
FROM dbo.foo GROUP BY grouping_column
) AS y
ON x.grouping_column = y.grouping_column
AND x.min_column = y.min_column;
SQL Server 2005+
;WITH x AS
(
SELECT grouping_column, min_column, other_columns,
rn = ROW_NUMBER() OVER (ORDER BY min_column)
FROM dbo.foo
)
SELECT grouping_column, min_column, other_columns
FROM x
WHERE rn = 1;
This subqery:
select distinct address_id, equipment_id,
min(datecreated) as datecreated, comment
from history where comment like 'MAC: 5%' group by equipment_id, address_id, comment
Probably will return multiple rows because the comment is not guaranteed to be the same.
Try this instead:
CROSS APPLY (
SELECT TOP 1 H2.DateCreated, H2.Comment -- H2.Equipment_id wasn't used
FROM History H2
WHERE
H2.Comment LIKE 'MAC: 5%'
AND C.Address_ID = H2.Address_ID
ORDER BY DateCreated
) H2
Switch that to OUTER APPLY in case you want rows that don't have a matching desired history entry.

Resources