Select value when it different from time between time - sql

I have Table:
I want to get value like this:
IP
Temp
Time
172.16.24.96
31.5
2021-07-24 11:17:46.000
172.16.24.96
31.4
2021-07-24 11:18:31.000
When it have same value in interval just get 1 value with the lowest Time.

If by "interval" you mean similar ip and Temp, then you can use the GROUP BY clause:
SELECT ip, Temp, MIN(Time)
FROM yourtable
GROUP BY ip, Temp;
EDIT
Larnu at the comment sections has pointed out that temperature might change and then change back. To cope with that issue, here's an adjusted query:
SELECT current.ip, current.Temp, current.Time
FROM yourtable current
LEFT JOIN yourtable previous
ON current.ip = previous.ip AND
current.Temp = previous.Temp AND
current.Time > previous.Time
LEFT JOIN yourtable betw
ON (current.ip <> betw.ip OR current.Temp <> betw.Temp) AND
betw.Time BETWEEN (previous.Time AND current.Time)
WHERE (previous.Temp IS NULL) OR
((NOT (previous.Temp IS NULL)) AND (NOT (betw.Temp IS NULL)))
GROUP BY current.ip, current.Temp, current(Time)
HAVING count(*) > 0

A simple method uses lag():
select t.*
from (select t.*,
lag(temp) over (partition by ip order by time) as prev_temp
from t
) t
where prev_temp is null or prev_temp <> temp;

Related

SQL - ROW_NUMBER that is used in a multi-condition LEFT JOIN

Two tables store different properties for each product: CTI_ROUTING_VIEW and ORD_MACH_OPS
They are both organized by SPEC_NO > MACH_SEQ_NO but the format of the Sequence number is different for each table so it can't be used for a JOIN. ORCH_MACH_OPS has MACHINE and PASS_NO, meaning if a product goes through the same machine twice, the row with the higher SEQ_NO will be PASS_NO 2, 3, etc. CTI_ROUTING_VIEW does not offer PASS_NO, but I can achieve the desired result with:
SELECT TOP (1000) [SPEC_NO]
,[SPEC_PART_NO]
,[MACH_NO]
,[MACH_SEQ_NO]
,[BLANK_WID]
,[BLANK_LEN]
,[NO_OUT_WID]
,[NO_OUT_LEN]
,[SU_MINUTES]
,[RUN_SPEED]
,[NO_COLORS]
,[PRINTDIEID]
,[CUTDIEID]
,ROW_NUMBER() OVER (PARTITION BY MACH_NO ORDER BY MACH_SEQ_NO) as PASS_NO
FROM [CREATIVE].[dbo].[CTI_ROUTING_VIEW]
I would think that I could use this artificial PASS_NO as a JOIN condition, but I can't seem to get it to come through. This is my first time using ROW_NUMBER() so I'm just wondering if I'm doing something wrong in the JOIN syntax.
SELECT rOrd.[SPEC_NO]
,rOrd.[MACH_SEQ_NO]
,rOrd.[WAS_REROUTED]
,rOrd.[NO_OUT]
,rOrd.[PART_COMP_FLG]
,rOrd.[SCHED_START]
,rOrd.[SCHED_STOP]
,rOrd.[MACH_REROUTE_FLG]
,rOrd.[MACH_DESCR]
,rOrd.REPLACED_MACH_NO
,rOrd.MACH_NO
,rOrd.PASS_NO
,rWip.MAX_TRX_DATETIME
,ISNULL(rWip.NET_FG_SUM*rOrd.NO_OUT,0) as NET_FG_SUM
,CASE
WHEN rCti.BLANK_WID IS NULL then 'N//A'
ELSE CONCAT(rCti.BLANK_WID, ' X ', rCti.BLANK_LEN)
END AS SIZE
,ISNULL(rCti.PRINTDIEID,'N//A') as PRINTDIEID
,ISNULL(rCti.CUTDIEID, 'N//A') as CUTDIEID
,rStyle.DESCR as STYLE
,ISNULL(rCti.NO_COLORS, 0) as NO_COLORS
,CAST(CONCAT(rOrd.ORDER_NO,'-',rOrd.ORDER_PART_NO) as varchar) as ORD_MACH_KEY
FROM [CREATIVE].[dbo].[ORD_MACH_OPS] as rOrd
LEFT JOIN (SELECT DISTINCT
[SPEC_NO]
,[SPEC_PART_NO]
,[MACH_NO]
,MACH_SEQ_NO
,[BLANK_WID]
,[BLANK_LEN]
,[NO_COLORS]
,[PRINTDIEID]
,[CUTDIEID]
,ROW_NUMBER() OVER (PARTITION BY MACH_NO ORDER BY MACH_SEQ_NO) as PASS_NO
FROM [CREATIVE].[dbo].[CTI_ROUTING_VIEW]) as rCti
ON rCti.SPEC_NO = rOrd.SPEC_NO
and rCti.MACH_NO =
CASE
WHEN rOrd.REPLACED_MACH_NO is null then rOrd.MACH_NO
ELSE rOrd.REPLACED_MACH_NO
END
and rCti.PASS_NO = rOrd.PASS_NO
LEFT JOIN INVENTORY_ITEM_TAB as rTab
ON rTab.SPEC_NO = rOrd.SPEC_NO
LEFT JOIN STYLE_DESCRIPTION as rStyle
ON rStyle.DESCR_CD = rTab.STYLE_CD
LEFT JOIN (
SELECT
JOB_NUMBER
,FORM_NO
,TRX_ORIG_MACH_NO
,PASS_NO
,SUM(GROSS_FG_QTY-WASTE_QTY) as NET_FG_SUM
,MAX(TRX_DATETIME) as MAX_TRX_DATETIME
FROM WIP_MACH_OPS
WHERE GROSS_FG_QTY <> 0
GROUP BY JOB_NUMBER, FORM_NO, TRX_ORIG_MACH_NO, PASS_NO) as rWip
ON rWip.JOB_NUMBER = rOrd.ORDER_NO
and rWip.FORM_NO = rOrd.ORDER_PART_NO
and rWip.TRX_ORIG_MACH_NO = rOrd.MACH_NO
and rWip.PASS_NO = rOrd.PASS_NO
WHERE rOrd.SCHED_START > DATEADD(DAY, -20, GETDATE())
I fixed it by adding a second partition.
ROW_NUMBER() OVER (PARTITION BY SPEC_NO, MACH_NO ORDER BY MACH_SEQ_NO) as PASS_NO

Return calculated column values for SELECT DISTINCT query

I have the following table in SQlite:
_id|token|status |timestamp|mood|eta|name|calc_eta
__________________________________________________________________________ 168|iqmC.3aHMBGbl|ok|1516625084498|50|-4154|Sample Name|1516625533082
169|iqmC.3aHMBGbl|ok|1516625084498|50|-4214|Sample Name|1516625533108
170|iqmC.3aHMBGbl|ok|1516625084498|50|-4274|Sample Name|1516625533414
171|iqmC.3aHMBGbl|ok|1516625084498|50|-4334|Sample Name|1516625533160
172|iqmC.3aHMBGbl|ok|1516625084498|50|-4394|Sample Name|1516625533680
173|iqmC.3aHMBGbl|ok|1516625084498|50|-4420|Sample Name|1516625533068
174|iqmC.3aHMBGbl|ok|1516625084498|50|-4428|Sample Name|1516625533482
175|iqmC.3aHMBGbl|ok|1516625084498|50|-4483|Sample Name|1516625533155
176|iqmC.3aHMBGbl|ok|1516625084498|50|-4543|Sample Name|1516625533148
177|TFbintkHMBw4H|ok|1516630122485|50|2526|Sample Name|1516632672019
178|TFbintkHMBw4H|ok|1516630122485|50|2520|Sample Name|1516632671903
179|TFbintkHMBw4H|ok|1516630122485|50|2460|Sample Name|1516632672321
180|TFbintkHMBw4H|ok|1516630122485|50|2344|Sample Name|1516632672859
181|TFbintkHMBw4H|ok|1516630122485|50|2336|Sample Name|1516632671939
182|TFbintkHMBw4H|ok|1516630122485|50|2281|Sample Name|1516632672802
183|TFbintkHMBw4H|ok|1516630122485|50|2220|Sample Name|1516632671828
184|TFbintkHMBw4H|ok|1516630122485|50|2161|Sample Name|1516632672625
I'm trying to come up with a query on it that would give me the difference between the two newest(based on auto-increment _id), calc_eta values for each distinct token value.
So in this case the result should be:
iqmC.3aHMBGbl|-7
TFbintkHMBw4H|797
I got this far with the SQL but it is not providing the calculated value for each distinct token currently and I'm not sure how to go further.
SELECT DISTINCT token,
(SELECT calc_eta
FROM DATA s
WHERE
(SELECT count(*)
FROM DATA f
WHERE f.token = s.token
AND f._id >= s._id) <= 1) -
(SELECT calc_eta
FROM
(SELECT calc_eta,
MIN(_id)
FROM DATA s
WHERE
(SELECT count(*)
FROM DATA f
WHERE f.token = s.token
AND f._id >= s._id) <= 2)) AS delay
FROM DATA;
In most SQL dialects, you would use window functions such as lag():
select d.*,
(calc_eta - prev_calc_eta) as diff
from (select d.*,
lag(calc_eta) over (partition by token order by _id) as prev_calc_eta,
row_number() over (partition by token order by _id desc) as seqnum
from data d
) d
where seqnum = 1;

Picking first instance in grouped rows- PostgreSQL

Here's the background, I have a set of rows:
I only want to get the first ADVANCE after every RECOVERY in the type column per accountid
so I the result should be the advances with procdates
2015-09-03 09:55:12.228343
2015-09-04 23:10:42.016903
Is this possible in one query?
Try this:
WITH CTE_PrevType
AS (
SELECT accountid
,procdate
,LAG(type, 1, NULL) OVER (
ORDER BY procdate
) AS PreviousType
FROM < Table_Name >
)
SELECT
accountid
,procdate
,type
,value
FROM < Table_Name > AS TN
INNER JOIN CTE_PrevType CPT
ON TN.accountid = CPT.accountid
AND TN.procdate = CPT.procdate
WHERE TN.type = 'ADVANCE'
AND CPT.type = 'RECOVERY'
I Have found on how to get it!
SELECT * FROM
(SELECT accountid,
procdate,
type,
value,
LAG(type) OVER (ORDER BY procdate ASC) AS previousType
FROM transaction) w WHERE previousType = 'RECOVERY';

Remove duplicates in SQL Result set of ONE table

Afternoon/Evening all,
I'm looking for the final touches to the below query. I need to remove the duplicate occurrences of a column in a particular row. Currently using the below SQL:
SELECT CBNEW.*
FROM CallbackNewID CBNEW
INNER JOIN (SELECT IDNEW, MAX(CallbackDate) AS MaxDate
FROM CallbackNewID
GROUP BY IDNEW) AS groupedCBNEW
ON (CBNEW.CallbackDate = groupedCBNEW.MaxDate) AND (CBNEW.IDNEW = groupedCBNEW.IDNEW);
My result set looks like the below
ID RecID Comp Rem Date_ IDNEW IDOLD CB? CallbackDate
138618 83209 1 0 2012-03-16 12:40:00 83209 83209 2 16-Mar-12
138619 83209 1 0 2012-03-16 12:40:00 83209 83209 2 16-Mar-12
110470 83799 1 0 2011-07-27 11:46:00 83799 83799 10 27-Jul-11
110471 83799 1 0 2011-07-27 11:46:00 83799 83799 10 27-Jul-11
This however gives me duplicate values in the CallBackDate and IDNEW Column because in the table there are some different Primary Keys with the same IDNEW and CallbackDate values.
If I dump this result into Excel, I can just use remove duplicates on the first ID column, and the problem's solved.
But what I want to do is make sure my result only includes the FIRST instance of the ID column, where IDNEW and CallbackDate are duplicated.
I'm sure I just need to append a tiny piece of SQL, but I'm stuck if I can find the answer so far.
Your help is very much appreciated.
Try adding MIN(ID) to the inner query and then adding it also on the ON clause:
SELECT CBNEW.*
FROM CallbackNewID CBNEW
INNER JOIN (SELECT IDNEW, MIN(ID) AS MinId, MAX(CallbackDate) AS MaxDate
FROM CallbackNewID
GROUP BY IDNEW) AS groupedCBNEW
ON (CBNEW.CallbackDate = groupedCBNEW.MaxDate)
AND (CBNEW.IDNEW = groupedCBNEW.IDNEW)
AND (CBNEW.ID = groupedCBNEW.MinId) ;
sqlfiddle demo
Here is a rather "brute force" approach. It just takes the results of your original query and does Min() on [ID], Max() on [Comp] and [Rem], and GROUP BY on everything else:
SELECT
Min(t.ID) AS MinOfID,
t.RecID,
Max(t.Comp) AS MaxOfComp,
Max(t.Rem) AS MaxOfRem,
t.Date_,
t.IDNEW,
t.IDOLD,
t.[CB?],
t.CallbackDate
FROM
(
SELECT CBNEW.*
FROM
CallbackNewID CBNEW
INNER JOIN
(
SELECT IDNEW, MAX(CallbackDate) AS MaxDate
FROM CallbackNewID
GROUP BY IDNEW
) AS groupedCBNEW
ON (CBNEW.CallbackDate = groupedCBNEW.MaxDate)
AND (CBNEW.IDNEW = groupedCBNEW.IDNEW)
) t
GROUP BY
t.RecID,
t.Date_,
t.IDNEW,
t.IDOLD,
t.[CB?],
t.CallbackDate;
It might not be terribly elegant, but if it works....
In MS SQL Server, I think you are looking for the ROW_NUMBER() function.
Something like this should help you get what you are looking for:
SELECT
X.*
FROM
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY DBNEW.IDNEW, DBNEW.MaxDate) [row_num]
FROM
CallbackNewID CBNEW
INNER JOIN
(
SELECT
IDNEW,
MAX(CallbackDate) AS MaxDate
FROM
CallbackNewID
GROUP BY
IDNEW
) AS groupedCBNEW ON (CBNEW.CallbackDate = groupedCBNEW.MaxDate) AND (CBNEW.IDNEW = groupedCBNEW.IDNEW)
) X
WHERE
X.row_num = 1
SELECT
A.*
FROM
(SELECT
*,
ROW_NUMBER() OVER (PARTITION BY IDNEW ORDER BY CallbackDate DESC)
AS [row_num]
FROM CallbackNewID
) A
WHERE
A.row_num = 1

Fastest way to check if the the most recent result for a patient has a certain value

Mssql < 2005
I have a complex database with lots of tables, but for now only the patient table and the measurements table matter.
What I need is the number of patient where the most recent value of 'code' matches a certain value. Also, datemeasurement has to be after '2012-04-01'. I have fixed this in two different ways:
SELECT
COUNT(P.patid)
FROM T_Patients P
WHERE P.patid IN (SELECT patid
FROM T_Measurements M WHERE (M.code ='xxxx' AND result= 'xx')
AND datemeasurement =
(SELECT MAX(datemeasurement) FROM T_Measurements
WHERE datemeasurement > '2012-01-04' AND patid = M.patid
GROUP BY patid
GROUP by patid)
AND:
SELECT
COUNT(P.patid)
FROM T_Patient P
WHERE 1 = (SELECT TOP 1 case when result = 'xx' then 1 else 0 end
FROM T_Measurements M
WHERE (M.code ='xxxx') AND datemeasurement > '2012-01-04' AND patid = P.patid
ORDER by datemeasurement DESC
)
This works just fine, but it makes the query incredibly slow because it has to join the outer table on the subquery (if you know what I mean). The query takes 10 seconds without the most recent check, and 3 minutes with the most recent check.
I'm pretty sure this can be done a lot more efficient, so please enlighten me if you will :).
I tried implementing HAVING datemeasurment=MAX(datemeasurement) but that keeps throwing errors at me.
So my approach would be to write a query just getting all the last patient results since 01-04-2012, and then filtering that for your codes and results. So something like
select
count(1)
from
T_Measurements M
inner join (
SELECT PATID, MAX(datemeasurement) as lastMeasuredDate from
T_Measurements M
where datemeasurement > '01-04-2012'
group by patID
) lastMeasurements
on lastMeasurements.lastmeasuredDate = M.datemeasurement
and lastMeasurements.PatID = M.PatID
where
M.Code = 'Xxxx' and M.result = 'XX'
The fastest way may be to use row_number():
SELECT COUNT(m.patid)
from (select m.*,
ROW_NUMBER() over (partition by patid order by datemeasurement desc) as seqnum
FROM T_Measurements m
where datemeasurement > '2012-01-04'
) m
where seqnum = 1 and code = 'XXX' and result = 'xx'
Row_number() enumerates the records for each patient, so the most recent gets a value of 1. The result is just a selection.