SQL Server : select multiple item code where date is max - sql

I have one table there have so many item code, then i select '09015','09002','09025','09026' these item code, where pat_no = '33516', the problem is how can i compare the max rpt_time from these item code??
Here is my T-SQL query:
SELECT
[pat_no],[item_code],[value],[rpt_time]
FROM
[Tmhtc_PHR].[dbo].[lab_item]
WHERE
[pat_no] = '33561'
AND ([item_code] = '09015' OR [item_code] = '09002' OR [item_code] = '09025' OR [item_code] = '09026')
ORDER BY
[rpt_time] DESC
Result:

You could use one of two queries below:
SELECT
pat_no, item_code, [value], rpt_time
FROM Tmhtc_PHR.dbo.lab_item
WHERE pat_no, item_code, rpt_time IN (
SELECT pat_no, item_code, MAX(rpt_time)
FROM Tmhtc_PHR.dbo.lab_item
WHERE pat_no = '33561'
AND item_code IN ('09015', '09002', '09025', '09026')
GROUP BY item_code
)
ORDER BY pat_no, item_code;
Or
SELECT
i.pat_no, i.item_code, i.[value], i.rpt_time
FROM Tmhtc_PHR.dbo.lab_item i
INNER JOIN (
SELECT pat_no, item_code, MAX(rpt_time) AS max_rpt_time
FROM Tmhtc_PHR.dbo.lab_item
WHERE pat_no = '33561'
AND item_code IN ('09015', '09002', '09025', '09026')
GROUP BY item_code
) im
ON i.pat_no = im.i.pat_no AND i.item_code = im.item_code AND i.rpt_time = im.max_rpt_time
ORDER BY i.pat_no, i.item_code;

Related

how to delete repeated values in UNION query using count

Hello I have been trying to delete a repeated value on the following UNION query with the following results (image). How can I filter out the value LW_ID=8232 with AANTALLN =0. I need to find a way taht if in the first query AANTALLN >0 is found, then on the second part of the union query not insert it again. Thanks "
With LESEENHEIDLOOPBAAN as (
SELECT
LE_AGENDA_FK,
LE_CODE,
LE_ID,
LE_KLAS_FK,
LE_KLASPARTITIE_FK,
LE_OMSCHRIJVING,
LE_VERANDERDDOOR,
LE_VERANDERDOP,
Count(LH_ID) As AantalLln
FROM
LESEENHEID
INNER JOIN LOOPBAANLESEENHEID on (LH_LESEENHEID_FK = LE_ID)
INNER JOIN LOOPBAAN ON (LH_LOOPBAAN_FK = LB_ID)
WHERE
(
'2022/09/28' BETWEEN LB_VAN
AND LB_TOT
)
AND (
LE_ID in (8277, 8276, 8232)
)
GROUP BY
LE_AGENDA_FK,
LE_CODE,
LE_ID,
LE_KLAS_FK,
LE_KLASPARTITIE_FK,
LE_OMSCHRIJVING,
LE_VERANDERDDOOR,
LE_VERANDERDOP
),
LESEENHEIDLOOPBAANNULL AS (
SELECT
LE_AGENDA_FK,
LE_CODE,
LE_ID,
LE_KLAS_FK,
LE_KLASPARTITIE_FK,
LE_OMSCHRIJVING,
LE_VERANDERDDOOR,
LE_VERANDERDOP,
0 As AantalLln
FROM
LESEENHEID
where
LE_ID in (8277, 8276, 8232)
and EXISTS (
SELECT
*
FROM
LESEENHEIDLOOPBAAN
)
)
SELECT
*
FROM
LESEENHEIDLOOPBAAN
UNION
SELECT
*
FROM
LESEENHEIDLOOPBAANNULL ROWS 1000
Try this out using ROW_NUMBER:
SELECT * FROM (
SELECT
ROW_NUMBER () OVER (PARTITION BY LW_ID ORDER BY AANTALLN DESC) AS RN
,* FROM
(
SELECT * FROM
LESEENHEIDLOOPBAAN
UNION
SELECT
*
FROM
LESEENHEIDLOOPBAANNULL ROWS 1000
)
)
) WHERE RN = 1
This way you eliminate the duplicates.

Select only the records with same values

I am working on a SQL statement that will become a part of a view. What I need is to extract only the records that have the same unique key twice. The query looks like below right now.
select distinct
rscmaster_no_in, rsc_no_in, calendar_year, calendar_month,
Wstat_Abrv_Ch,
h.Wstat_no_in, Staffing_Calendar_Date, payhours,
l.OTStatus
from
vw_all_ts_hire h
left join
MCFRS_OTStatus_Lookup l on l.wstat_no_in = h.Wstat_no_in
where
rscmaster_no_in in (select rscmaster_no_in from vw_rsc_ECC_splty)
and Wstat_Abrv_Ch <> ''
and h.Wstat_no_in in (103, 107)
and l.OTStatus in ('ECCOTRemove', 'ECCOTSignup')
and Staffing_Calendar_Date = '2020-11-01' -- only for the testing purposes. Will be removed later.
order by
RscMaster_no_in
The result I get from the query above is:
I need to modify the SQL statement so that the end result is like below:
How can I modify the above statement to spit out the end result like that?
Use the analytic count(*) over () function.
with cte as (
select
count(*) over (partition by YourUniqueKey) as MyRowCount
{rest of your query}
)
select *
from cte
where MyRowCount = 2;
This should give you the results you want (performance is dependent on indexes/table design).
This takes your core logic and puts it into a sub select that only returns records that have a count > 1.
Then use those ID's to select all the data you need but only for those ID's that are in the sub select with count > 1
select distinct rscmaster_no_in,rsc_no_in, calendar_year, calendar_month,
Wstat_Abrv_Ch, h.Wstat_no_in, Staffing_Calendar_Date, payhours ,l.OTStatus
from vw_all_ts_hire h
left join MCFRS_OTStatus_Lookup l on l.wstat_no_in = h.Wstat_no_in
WHERE rscmaster_no_in IN (
SELECT rscmaster_no_in
from vw_all_ts_hire h
left join MCFRS_OTStatus_Lookup l on l.wstat_no_in = h.Wstat_no_in
where rscmaster_no_in in (select rscmaster_no_in from vw_rsc_ECC_splty)
and Wstat_Abrv_Ch <> ''
and h.Wstat_no_in in (103, 107)
and l.OTStatus in ('ECCOTRemove', 'ECCOTSignup')
and Staffing_Calendar_Date = '2020-11-01' -- only for the testing purposes. Will be removed later.
GROUP BY rscmaster_no_in
HAVING COUNT(*) > 1
)
order by RscMaster_no_in
You can use COUNT(*) OVER () window function such as
SELECT *
FROM
(
SELECT COUNT(*) OVER (PARTITION BY rscmaster_no_in) AS cnt,
t.*
FROM tab t
) t
WHERE cnt>1
AND OTStatus = 'ECCOTRemove'
This may help you :
select * from (
select distinct
rscmaster_no_in, rsc_no_in, calendar_year, calendar_month,
Wstat_Abrv_Ch,
h.Wstat_no_in, Staffing_Calendar_Date, payhours,
l.OTStatus,
SELECT COUNT(*) OVER (PARTITION BY rscmaster_no_in) AS uinqueCount
from
vw_all_ts_hire h
left join
MCFRS_OTStatus_Lookup l on l.wstat_no_in = h.Wstat_no_in
where
rscmaster_no_in in (select rscmaster_no_in from vw_rsc_ECC_splty)
and Wstat_Abrv_Ch <> ''
and h.Wstat_no_in in (103, 107)
and l.OTStatus in ('ECCOTRemove', 'ECCOTSignup')
and Staffing_Calendar_Date = '2020-11-01' -- only for the testing purposes. Will be removed later.
) innerReult
where uinqueCount=2 --Or uinqueCount>1 base on your business
order by
RscMaster_no_in

Update table with another column in the same table

I have a table like this
Test_order
Order Num Order ID Prev Order ID
987Y7OP89 919325 0
987Y7OP90 1006626 919325
987Y7OP91 1029350 1006626
987Y7OP92 1756689 0
987Y7OP93 1756690 0
987Y7OP94 1950100 1756690
987Y7OP95 1977570 1950100
987Y7OP96 2160462 1977570
987Y7OP97 2288982 2160462
Target table should be like below,
Order Num Order ID Prev Order ID
987Y7OP89 919325 0
987Y7OP90 1006626 919325
987Y7OP91 1029350 1006626
987Y7OP92 1756689 1029350
987Y7OP93 1756690 1756689
987Y7OP94 1950100 1756690
987Y7OP95 1977570 1950100
987Y7OP96 2160462 1977570
987Y7OP97 2288982 2160462
987Y7OP97 2288900 2288982
Prev Order ID should be updated with the Order ID from the previous record from the same table.
I'm trying to create a dummy data set and update..but it's not working..
WITH A AS
(SELECT ORDER_NUM, ORDER_ID, PRIOR_ORDER_ID,ROWNUM RID1 FROM TEST_ORDER),B AS (SELECT ORDER_NUM, ORDER_ID, PRIOR_ORDER_ID,ROWNUM+1 RID2 FROM TEST_ORDER)
SELECT A.ORDER_NUM,B.ORDER_ID,A.PRIOR_ORDER_ID,B.PRIOR_ORDER_ID FROM A,B WHERE RID1 = RID2
You could use Oracles Analytical Functions (also called Window functions) to pick up the value from the previous order:
UPDATE Test_Order
SET ORDERID = LAG(ORDERID, 1, 0) OVER (ORDER BY ORDERNUM ASC)
WHERE PrevOrderId = 0
See here for the documentation on LAG()
In sql-server you cannot use window function in update statement, not positive but don't think so in Oracle either. Anyway to get around that you can just update a cte as follows.
WITH cte AS (
SELECT
*
,NewPreviousOrderId = LAG(OrderId,1,0) OVER (ORDER BY OrderNum)
FROM
TableName
)
UPDATE cte
SET PrevOrderId = NewPreviousOrderId
And if you want to stick with the ROW_NUMBER route you were going this would be the way of doing it.
;WITH cte AS (
SELECT
*
,ROW_NUMBER() OVER (ORDER BY OrderNum) AS RowNum
FROM
TableName
)
UPDATE c1
SET PrevOrderId = c2.OrderId
FROM
cte c1
INNER JOIN cte c2
ON (c1.RowNum - 1) = c2.RowNum

TSQL Pivot Throwing Syntax Errors

I would like to PIVOT the following query result to display a column for each Project Status Code.
WITH r AS (
SELECT ROW_NUMBER() OVER (ORDER BY ph.InsertedDateTime) rownum,
CAST(ph.InsertedDateTime AS DATE) InsertedDate, ph.Gate_1_TargetDate, ph.Gate_2_TargetDate, ph.Gate_3_TargetDate
FROM PROJECT_HIST ph
JOIN (
SELECT ProjectID, MAX(InsertedDateTime) InsertedDateTime
FROM PROJECT_HIST
GROUP BY ProjectID, CAST(InsertedDateTime AS DATE)
) ph_distinct_date ON ph_distinct_date.InsertedDateTime = ph.InsertedDateTime
AND ph_distinct_date.ProjectID = ph.ProjectID
WHERE ph.projectid = 100957
AND NOT (
ph.Gate_1_TargetDate IS NULL
AND ph.Gate_2_TargetDate IS NULL
AND ph.Gate_3_TargetDate IS NULL
)
),
fubar AS (
SELECT rownum, InsertedDate, 0 gateName, NULL targetDate FROM r
UNION ALL
SELECT rownum, InsertedDate, 1, Gate_1_TargetDate FROM r
UNION ALL
SELECT rownum, InsertedDate, 2, Gate_2_TargetDate FROM r
UNION ALL
SELECT rownum, InsertedDate, 3, Gate_3_TargetDate FROM r
)
SELECT f1.InsertedDate 'Change Date', f1.gateName 'ProjectStageCode', f1.targetDate
FROM fubar f1
LEFT JOIN fubar f2 ON f2.rownum = f1.rownum - 1
AND f2.gateName = f1.gateName
PIVOT(min(f1.InsertedDate) FOR f1.gateName IN ([0],[1],[2],[3])) AS p
WHERE f1.rownum = 1
OR f1.targetDate <> f2.targetDate
ORDER BY f1.InsertedDate
;
Without the pivot attempt, this query currently returns this result for this particular project:
What I would like to do is pivot the query to create columns for each Project Stage Code to match the following result:
Essentially, I need to have a row for each unique Change Date and have the targetDate column value fill in the respective newly pivoted numerical ProjectStageCode column.
From the looks of it it seems like you just need to use a subquery before you try to PIVOT the data. You also need to aggregate the targetDate instead of the InsertedDate:
WITH r AS
(
SELECT ROW_NUMBER() OVER (ORDER BY ph.InsertedDateTime) rownum,
CAST(ph.InsertedDateTime AS DATE) InsertedDate, ph.Gate_1_TargetDate, ph.Gate_2_TargetDate, ph.Gate_3_TargetDate
FROM PROJECT_HIST ph
JOIN
(
SELECT ProjectID, MAX(InsertedDateTime) InsertedDateTime
FROM PROJECT_HIST
GROUP BY ProjectID, CAST(InsertedDateTime AS DATE)
) ph_distinct_date
ON ph_distinct_date.InsertedDateTime = ph.InsertedDateTime
AND ph_distinct_date.ProjectID = ph.ProjectID
WHERE ph.projectid = 100957
AND NOT (ph.Gate_1_TargetDate IS NULL
AND ph.Gate_2_TargetDate IS NULL
AND ph.Gate_3_TargetDate IS NULL)
),
fubar AS
(
SELECT rownum, InsertedDate, 0 gateName, NULL targetDate FROM r
UNION ALL
SELECT rownum, InsertedDate, 1, Gate_1_TargetDate FROM r
UNION ALL
SELECT rownum, InsertedDate, 2, Gate_2_TargetDate FROM r
UNION ALL
SELECT rownum, InsertedDate, 3, Gate_3_TargetDate FROM r
)
SELECT ChangeDate, [0],[1],[2],[3]
FROM
(
SELECT f1.InsertedDate ChangeDate, f1.gateName, f1.targetDate
FROM fubar f1
LEFT JOIN fubar f2
ON f2.rownum = f1.rownum - 1
AND f2.gateName = f1.gateName
WHERE f1.rownum = 1
OR f1.targetDate <> f2.targetDate
) d
PIVOT
(
min(targetDate)
FOR gateName IN ([0],[1],[2],[3])
) AS p;

SQL group by issue when i try to get some info

I can not figure it out:
I have a table called ImportantaRecords with fields like market, zip5, MHI, MHV, TheTable and I want to group all the records by zip5 that have TheTable = 'mg'… I tried this :
select a.Market,a.zip5,count(a.zip5),a.MHI,a.MHV,a.TheTable from
(select * from ImportantaRecords where TheTable = 'mg') a
group by a.Zip5
but it gives me the classic error with not an aggrefate function
and then I tried this:
select Market,zip5,count(zip5),MHI,MHV,TheTable from ImportantaRecords where TheTable = 'mg'
group by Zip5
and the same thing…
any help ?
You did not state what database you are using but if you are getting an error about columns not being in an aggregate function, then you might need to add the columns not in an aggregate function to the GROUP BY:
select Market,
zip5,
count(zip5),
MHI,
MHV,
TheTable
from ImportantaRecords
where TheTable = 'mg'
group by Market, Zip5, MHI, MHV, TheTable;
If grouping by the additional columns alters the result that you are expecting, then you could use a subquery to get the result:
select i1.Market,
i1.zip5,
i2.Total,
i1.MHI,
i1.MHV,
i1.TheTable
from ImportantaRecords i1
inner join
(
select zip5, count(*) Total
from ImportantaRecords
where TheTable = 'mg'
group by zip5
) i2
on i1.zip5 = i2.zip5
where i1.TheTable = 'mg'