How to select top (5) rows with specified Id and latest date? - sql

The table is this:
Id_P Id_Utente PasswordOld_ DateOld_
1 134 E0476F2E85A84FB4E68AA26A841A86FA 8/01/2015 10:30:00 PM
2 134 9C454981DE1702C7AAD3B435B51404EE 8/02/2015 10:30:00 PM
3 134 BA0D9BE25565C34CAAD3B435B51404EE 8/03/2015 10:30:00 PM
4 134 9C6C9E34FB63DC9DE68AA26A841A86FA 8/04/2015 10:30:00 PM
5 134 14BEE187F918F8817584248B8D2C9F9E 8/04/2015 10:30:00 PM
6 135 9A70F4507624037CAAD3B435B51404EE 15/01/2015 10:30:00 PM
7 135 C3DB775AE3B3BD29E68AA26A841A86FA 15/02/2015 10:30:00 PM
8 135 0BB76B9CA33D8E31AAD3B435B51404EE 15/03/2015 10:30:00 PM
9 136 9A70F4507624037CAAD3B435B51404EE 26/01/2015 10:30:00 PM
10 136 C3DB775AE3B3BD29E68AA26A841A86FA 26/02/2015 10:30:00 PM
11 136 0BB76B9CA33D8E31AAD3B435B51404EE 26/03/2015 10:30:00 PM

You can use limit or top. Try this:
SELECT TOP 5 * FROM yourTablename ORDER BY DateOld_ DESC, Id_P DESC;
SELECT LIMIT is not supported in all SQL databases. But you can use the query above for SQL Server or MSAccess and the below query for mysql specifically.
SELECT * FROM yourTablename ORDER BY DateOld_ DESC LIMIT 5;
For more info, you can visit this link.

Use a order by clause
select top 5 *
from table1
where Id_P in (1,2,3,4,5)
order by DateOld_;

LIMIT is the best way.
Use it like:
SELECT *
FROM TABLE_NAME
LIMIT 5

As your DateOld_ field is of type ntext, you cannot do an order by on that. To sort the results based on that column, you need to convert the values in to datetime format.
You can execute the following query to fetch 5 rows with id_utente = 134 and sorted in descending order as per the time:
select top 5 * from table1
where id_utente = 134
order by convert(datetime, convert(varchar, dateold_)) desc;
SQLFiddle Example

Related

Sql query to select the records for past 60 seconds and compare the temperature of the selected records and if any record has higher value then ignore

I am trying to eliminate the data anomalies in the data I am receiving from eventhub and send only selected data to azure functions through Azure stream analytics for that I am writing a sql query where I need some help
Requirement: I need to collect the past 60 seconds data and need to group by Id and compare the records that I received in the 60 seconds and If any record value is way higher than the selected values than ignore that record (for example, I will collect the 4 records in past 60 seconds and if the data is 40 40 40 40 5. We should drop the 5. Example 2 - 20 20 20 500 drop the 500. ).
My sql table will be something like this:
id Temp date datetime
123 30 2023-01-01 2023-01-01 12:00:00
124 35 2023-01-01 2023-01-01 12:00:00
123 31 2023-01-01 2023-01-01 12:00:00
123 33 2023-01-01 2023-01-01 12:00:00
123 60 2023-01-01 2023-01-01 12:00:00
124 36 2023-01-01 2023-01-01 12:00:00
124 36 2023-01-01 2023-01-01 12:00:00
124 8 2023-01-01 2023-01-01 12:00:00
124 36 2023-01-01 2023-01-01 12:00:00
I need to eliminate the records that are not in the range with the other records
I'll leave the details of the comparison up to you, but you can use a CROSS APPLY to gather the data for comparison.
Something like:
SELECT *
FROM TemperatureData T
CROSS APPLY (
SELECT AVG(T2.Temp * 1.0) AS PriorAvgTemp, COUNT(*) As PriorCount
FROM TemperatureData T2
WHERE T2.id = T.id
AND T2.datetime >= DATEADD(second, -60, T.datetime)
AND T2.datetime < T.datetime
) P
WHERE T.Temp BETWEEN P.PriorAvgTemp - 10 AND P.PriorAvgTemp + 10
--OR P.PriorCount < 3 -- Should we allow if there is insufficient prior data
--AND P.PriorCount >= 3 -- Should we omit if there is insufficient prior data
Be sure you have an index on TemperatureData(id, datetime).
If you are willing to accept the last N values instead of a time range, windowed aggregate calculation may be more efficient.
SELECT *
FROM (
SELECT *,
AVG(T.Temp * 1.0)
OVER(PARTITION BY id ORDER BY datetime
ROWS BETWEEN 60 PRECEDING AND 1 PRECEDING)
AS PriorAvgTemp,
COUNT(*)
OVER(PARTITION BY id ORDER BY datetime
ROWS BETWEEN 60 PRECEDING AND 1 PRECEDING)
AS PriorCount
FROM TemperatureData T
) TT
WHERE TT.Temp BETWEEN TT.PriorAvgTemp - 10 AND TT.PriorAvgTemp + 10
--OR TT.PriorCount < 3 -- Should we allow if there is insufficient prior data
--AND TT.PriorCount >= 3 -- Should we omit if there is insufficient prior data
Please note: The above is untested code, which may need some syntax fixes and debugging. If you discover errors, please comment and I will correct the post.

Access SQL Query to Count Unique Occurrences of One Field Matching Multiple Parameters/Rows, Some Identical

Struggling with ms-access's flavor of SQL queries still, though I've made some progress (thanks to y'all). I have an event log table like this:
Logs Table
logID (auto#)
modID (str)
relID (str)
DateTime (date)
TxType (short)
1
1234
22.3
10/1/22 0800
6
2
1234
22.3
10/1/22 0900
7
3
1234
22.3
10/1/22 1000
13
4
1234
22.3
10/1/22 1100
15
5
4321
22.3
10/1/22 0830
1
6
4321
22.3
10/1/22 0930
13
7
4321
22.3
10/1/22 1030
15
8
4321
22.3
10/1/22 1130
13
9
1234
23.1
11/1/22 0800
1
10
1234
23.1
11/1/22 0900
15
11
1234
23.1
11/1/22 1000
13
12
1234
23.1
11/1/22 1100
15
13
4321
23.1
11/1/22 0830
13
14
4321
23.1
11/1/22 0930
7
15
4321
23.1
11/1/22 1030
13
16
4321
23.1
11/1/22 1130
15
What I need to do is:
filter the table by relID, then
count the number of modID's that have a 15 txType as the last/most recent chronological event in their rows.
So ideally I'd filter e.g. by relID=23.1 and get these results (but not logID # 10 for example) and then count them:
logID (auto#)
modID (str)
relID (str)
DateTime (date)
TxType (short)
12
1234
23.1
11/1/22 1100
15
16
4321
23.1
11/1/22 1130
15
As part of another function I have been able to count any modID's having a single txType successfully using
SELECT COUNT(*)
FROM (
SELECT DISTINCT Logs.modID, Logs.relID
FROM Logs
WHERE ((Logs.relID='23.1') AND ((Logs.TxType=13)))
);
Another stackoverflow user (exception - thanks!) showed me how to get the last event type for a given modID, relID combination using
SELECT TOP 1 TxType
FROM Logs
WHERE (((Logs.modID=[EnterModID])) AND ((Logs.relID=[EnterRelID])))
ORDER BY DateTime DESC;
But I'm having trouble combining these two. I know I can combine COUNT and GROUP BY but Access treats GROUP BY very particularly, and I'm not sure how to use SELECT TOP to get the latest events for each modID rather than just the latest events in the table, period.
This should give you the logID from the row with the latest DateTime for each combination of modIDand your target relID:
PARAMETERS which_relID Text(255);
SELECT DISTINCT
(
SELECT TOP 1 logID
FROM Logs
WHERE modID=l.modID AND relID=l.relID
ORDER BY [DateTime] DESC
) AS latest_modID
FROM Logs AS l
WHERE l.relID=[which_relID]
Use it as a subquery which you INNER JOIN to your Logs table. Note the subquery evaluates rows regardless of TxType. So have the parent query select only rows whose TxType = 15
PARAMETERS which_relID Text(255);
SELECT l2.*
FROM
Logs AS l2
INNER JOIN
(
SELECT DISTINCT
(
SELECT TOP 1 logID
FROM Logs
WHERE modID=l.modID AND relID=l.relID
ORDER BY [DateTime] DESC
) AS latest_modID
FROM Logs AS l
WHERE l.relID=[which_relID]
) AS sub
ON l2.logID=sub.latest_modID
WHERE l2.TxType=15;
Note I moved the PARAMETERS clause into the parent query. But you can eliminate it altogether if you believe it's causing trouble.
DateTime is a reserved word. I enclosed it in square brackets to ensure Access understands we mean the name of an object.
Using your sample data, I get these 2 rows when I supply 23.1 for the query parameter:
logID
modID
relID
DateTime
TxType
12
1234
23.1
11/1/2022 11:00:00 AM
15
16
4321
23.1
11/1/2022 11:30:00 AM
15
I get a single row with 22.3 for the parameter:
logID
modID
relID
DateTime
TxType
4
1234
22.3
10/1/2022 11:00:00 AM
15

How to use the join keyword to join two tables in SQL Server

I do not know how to use the join keyword in the following situation. I have two tables and i need to join them in one table. This is the code
use DEV
select top 10
Casa_de_marcat,
Numar_bon,
Data_bon
from antetBonuri
where Casa_de_marcat=1
order by Data_bon desc
use DEV
select top 10
Total,
Data,
Ora,
Vinzator
from bp
order by Data desc
these are the results from the two tables
Casa_de_marcat Numar_bon Data_bon
-------------- ----------- -----------------------
1 NULL 2018-05-12 00:00:00.000
1 1 2018-04-13 00:00:00.000
1 NULL 2018-03-16 00:00:00.000
1 NULL 2018-03-16 00:00:00.000
1 1 2018-02-16 00:00:00.000
1 1 2018-02-05 00:00:00.000
1 NULL 2018-02-05 00:00:00.000
1 NULL 2018-02-05 00:00:00.000
1 10 2017-11-02 00:00:00.000
1 NULL 2017-09-29 00:00:00.000
(10 rows affected)
Total Data Ora Vinzator
---------------------- ----------------------- ------ ----------
12 2019-11-15 00:00:00.000 1150 naomi
12 2019-11-15 00:00:00.000 1150 naomi
82 2019-10-17 00:00:00.000 1035 MIHAI
12 2019-10-17 00:00:00.000 1038 MIHAI
12 2019-10-17 00:00:00.000 1043 MIHAI
12 2019-10-17 00:00:00.000 1044 MIHAI
12 2019-10-17 00:00:00.000 1044 MIHAI
12 2019-10-17 00:00:00.000 1053 MIHAI
12 2019-10-17 00:00:00.000 1105 MIHAI
12 2019-10-17 00:00:00.000 1108 MIHAI
(10 rows affected)
the final results should be all the above columns joined in a single table , the order does not count.
And yes, my bad, im using SQL server
A FULL JOIN technically does what you want:
select ab.*, bp.*
from (select top 10 Casa_de_marcat, Numar_bon, Data_bon
from antetBonuri
where Casa_de_marcat = 1
order by Data_bon desc
) ab full join
(select top 10 Total, Data, Ora, Vinzator
from bp
order by Data desc
) bp
on 1 = 0; -- never matches
There are no obvious JOIN keys.
This produces 20 rows with all the columns. In each row, one of the sets of columns (per subquery) will all be NULL.
That appears to be what you are asking for. I'm not sure how useful this is. Or why you would prefer using JOIN rather than UNION ALL to get this.
EDIT:
It also strikes me that you might want 10 rows side-by-side. If so, then use row_number():
select ab.Casa_de_marcat, ab.Numar_bon, ab.Data_bon,
bp.Total, bp.Data, bp.Ora, bp.Vinzator
from (select top 10 Casa_de_marcat, Numar_bon, Data_bon,
row_number() over (order by (select null)) as seqnum
from antetBonuri
where Casa_de_marcat = 1
order by Data_bon desc
) ab full join
(select top 10 Total, Data, Ora, Vinzator,
row_number() over (order by (select null)) as seqnum
from bp
order by Data desc
) bp
on ab.seqnum = bp.seqnum;
This results in 10 rows with the results "side-by-side". The rows from the two tables are in an arbitrary order.

sql query for difference between current row and previous row based on datetime

i have a small issue in sql query. I am using SQL Server 2008 Database, i want to calculate the difference between current row and previous row of column cumulativeValue based on datetime in where condition i need to pass siteid, from date and todate in between days i need to get the data. the table is below:
ID siteId readtime cumulativeValue
1 GAF1608187 2017-10-18 12:59:03.000 20
2 GAF1604620 2017-10-18 11:38:33.000 10
3 GAF1608187 2017-10-19 14:59:00.000 40
4 GAF1608187 2017-10-19 16:07:46.000 65
5 GAF1604620 2017-10-19 11:41:49.000 55
6 GAF1604620 2017-10-20 10:52:35.000 120
7 GAF1608187 2017-10-20 16:10:15.000 90
8 GAF1608187 2017-10-21 16:13:19.000 120
9 GAF1604620 2017-10-21 11:44:42.000 180
10 GAF1604620 2017-10-22 11:05:50.000 230
Output should be:
ID siteId readtime cumulativeValue difference
2 GAF1604620 2017-10-18 11:38:33.000 10 10
5 GAF1604620 2017-10-19 11:41:49.000 55 45
6 GAF1604620 2017-10-20 10:52:35.000 120 75
9 GAF1604620 2017-10-21 11:44:42.000 180 60
10 GAF1604620 2017-10-22 11:05:50.000 230 50
Please help me in this query thank you :-)
In SQL Server 2012+, you can use lag(). In SQL Server 2008, use apply:
select t.*,
coalesce(t.cumulativeValue - tprev.cumulativeValue, t.cumulativeValue) as diff
from t outer apply
(select top 1 tprev.*
from t tprev
where tprev.siteId = t.siteId and tprev.readtime < t.readtime
order by tprev.readtime desc
) tprev;
You van use common table expression and ROW_Number() and join the rows on A.row = B.row - 1. Like this:
WITH CTE AS
(
SELECT TOP 10 DATECOLUMN, ROW_NUMBER() OVER (ORDER BY DATECOLUMN) AS ROW_Num
FROM Table_A
)
SELECT * FROM CTE AS A
INNER JOIN CTE AS B ON A.ROW_Num = B.ROW_Num - 1
ORDER BY A.ROW_Num

ORACLE SQL Select timestamps column from table. Producing more results than intended

Hello currently I have a working script below. I am using Oracle 10
SELECT z.no as "ID_One",
MAX(r.value) as "Max",
round(MAX(r.value)/80000,2) as "ROUND"
FROM Table1 r, Table2 z
WHERE r.timestamp > ((SYSDATE - TO_DATE('01/01/1970 00:00:00', 'MM-DD-YYYY HH24:MI:SS')) * 24 * 60 * 60) - 80000
AND r.va=21
AND r.nor IN ('7','98','3','3')
AND r.nor = z.re
GROUP BY r.nor, r.varr, z.no;
It produces a table like this
ID_ONE MAX ROUND
105 500 232
106 232 32
333 23 .21
444 34 .321
I want to select a row call timestamp from table r. However when I add " r.timestamp " in to my query it produces 500 rows of data instead of 4. It looks like it is producing the the highest number for each timestamp instead. How would I produce a table that looks like this ? fyi timestamp column is in unix time. I can do the conversion myself. I just need to know how to get out these rows.
ID_ONE MAX ROUND TIMESTAMP
105 500 232 DEC 21,2021 10:00
106 232 32 DEC 21,2021 23:12
333 23 .21 DEC 31,2021 2:12
444 34 .321 DEC 31,2021 23:12
When I add the column time stamp it does not create what is above. What I am getting instead is something like that looks like this the other two ids are below in this 500 long row of data. I only wanted the 4 that is the highest value (MAX) from this set of time. ID_ONE is my id for a stock of inventory for a warehouse.
ID_ONE ROUND TIMESTAMP MAX
106 338
.06 1406694567
106 355
.06 1406696037
106 246
.04 1406696337
106 363
.06 1406700687
106 330
.06 1406700987
106 512
.09 1406701347
106 459
.08 1406704047
106 427
.07 1406711038
106 596
.1 1406713111
106 401
.07 1406715872
106 682
.11 1406726192
106 2776
.46 1406726492
105 414
.07 1406728863
105 380
.06 1406734055
105 378
.06 1406734655
105 722
.12 1406735555
105 144
.02 1406665697
105 5
I have edited my answer kindly try the below
SELECT z.no as "ID_One",
max(r.value) as "Max",
round(MAX(r.value)/80000,2) as "ROUND",r.Timestamp
FROM Table1 r, Table2 z
where r.timestamp > ((SYSDATE - TO_DATE ('01/01/1970 00:00:00', 'MM
-DD-YYYY HH24:MI:SS')) * 24 * 60 * 60) - 80000
and r.va=21
AND r.nor IN ('7','98','3','3')
AND r.value=(select max(r1.value) from Table1 r1 where r1.va=r.va and r1.nor=r.nor)
AND r.nor = z.re group by r.nor, r.varr, z.no;
This looks like an ideal use case for analytic functions:
SELECT
v1.*,
round(v1.value/80000,2) as rounded_max_value
FROM (
SELECT
z.no as id_one,
r.value,
row_number() over (partition by r.nor, r.varr, z.no order by r.value desc) as rn,
r.timestamp
FROM Table1 r, Table2 z
WHERE r.timestamp >
((SYSDATE - TO_DATE('01/01/1970 00:00:00', 'MM-DD-YYYY HH24:MI:SS')) * 24 * 60 * 60) - 80000
AND r.va=21
AND r.nor IN ('7','98','3','3')
AND r.nor = z.re
) v1
where v1.rn = 1
This query
uses row_number over (partition by .. order by ) to get an ordering of the rows within a group
uses rn = 1 in the outer query to get only the row having the maximum value
Some additional recommendations:
if your r.nor column is numeric, then don't use string literals; use IN (7,98,3,3) instead (BTW: why do you have 3 twice in your IN list?
don't use " for column aliases unless absolutely necessary (since it makes them case-sensitive) ; they are a PITA
don't put your JOIN conditions into the WHERE clause; it makes your query harder to read. Use ANSI style joins instead.