Select last two values from two IDs - mysql

I would like to select two specific values, the first value is the last inserted row where the ID_SENSOR is 1, and the second value is the last inserted row where the ID_SENSOR is 2.
My Database table:
My Query:
SELECT DATA FROM (SELECT * FROM registovalores WHERE ID_SENSOR = '1' OR ID_SENSOR = '2' ORDER BY ID_SENSOR DESC LIMIT 2) as r ORDER BY TIMESTAMP
My Query is printing the last value just from the ID_SENSOR 1, which it means that I'm only getting the last inserted values, and not the last inserted value from both IDS.
I would like to print my values like this:
ID_SENSOR 1 = 90
ID SENSOR 2 = 800
What do I need to change on my Query?
Thank you.

One method uses a correlated subquery:
SELECT rv.*
FROM registovalores rv
WHERE rv.ID_SENSOR IN (1, 2) AND
rv.TIMESTAMP = (SELECT MAX(rv2.TIMESTAMP)
FROM registovalores rv2
WHERE rv.ID_SENSOR = rv2.ID_SENSOR
);

You have to have two separate queries, one per sensor.
select id_sensor, data
from the_table
where id_sensor = 'sensor_1'
order by timestamp desc -- the latest value is the first to come
limit 1; -- only pick the top (latest) row.
If you want to query for more than one value in a single database roundtrip, consider using union all between several such queries.
Please note that such a query may return one row or zero rows, since data for a particular sensor may not be available yet.

Related

Why offset. limit returns all rows?

The following SQL query return all rowsa instead from 12 to 18.
SELECT `reviews`.*,
`users`.`username` as `user_username`,
`users`.`slug` as `user_slug`
FROM `reviews`
JOIN `users` ON `users`.`id` = `reviews`.`user_id`
WHERE `reviews`.`product_id` = 2
ORDER BY `reviews`.`created_at` DESC LIMIT 12, 18
As result I have to get 6 rows instead all.
Using the OFF SET in the LIMIT query
The OFF SET value is also most often used together with the LIMIT keyword. The OFF SET value allows us to specify which row to start from retrieving data
Let’s suppose that we want to get a limited number of members starting from the middle of the rows, we can use the LIMIT keyword together with the offset value to achieve that. The script shown below gets data starting the second row and limits the results to 2.
SELECT * FROM `members` LIMIT 1, 2;
Refrence and MySQL docs
In your case to return only 6 rows starting from 12(thirteen row) it should be ORDER BY reviews.created_at DESC LIMIT 12, 6

Sql select where array in column

In my query I use join table category_attributes. Let's assume we have such rows:
category_id|attribute_id
1|1
1|2
1|3
I want to have the query which suites the two following needs. I have a variable (php) of allowed attribute_id's. If the array is subset of attribute_id then category_id should be selected, if not - no results.
First case:
select * from category_attributes where (1,2,3,4) in category_attributes.attribute_id
should give no results.
Second case
select * from category_attributes where (1,2,3) in category_attributes.attribute_id
should give all three rows (see dummy rows at the beginning).
So I would like to have reverse side of what standard SQL in does.
Solution
Step 1: Group the data by the field you want to check.
Step 2: Left join the list of required values with the records obtained in the previous step.
Step 3: Now we have a list with required values and corresponding values from the table. The second column will be equal to required value if it exist in the table and NULL otherwise.
Count null values in the right column. If it is equal to 0, then it means table contains all the required values. In that case return all records from the table. Otherwise there must be at least one required value is missing in the table. So, return no records.
Sample
Table "Data":
Required values:
10, 20, 50
Query:
SELECT *
FROM Data
WHERE (SELECT Count(*)
FROM (SELECT D.value
FROM (SELECT 10 AS value
UNION
SELECT 20 AS value
UNION
SELECT 50 AS value) T
LEFT JOIN (SELECT value
FROM Data
GROUP BY value) D
ON ( T.value = D.value )) J
WHERE value IS NULL) = 0;
You can use group by and having:
select ca.category_id
from category_attributes ca
where ca.attribute_id in (1, 2, 3, 4)
group by ca.category_id
having count(*) = 4; -- "4" is the size of the list
This assumes that the table has no duplicates (which is typical for attribute mapping tables). If that is a possibility, use:
having count(distinct ca.attribute_id) = 4
You can aggregate attribute_id into array and compare two array from php.
SELECT category_id FROM
(select category_id, group_concat(attribute_id) as attributes from category_attributes
order by attribute_id) t WHERE t.attributes = (1, 2, 3);
But you need to find another way to compare arrays or make sure that array is always sorted.

group by id in descending order in select statement

I have MySQL statement where I'm trying to select distinct rows with the latest date.
This is the SQL statement:
SELECT st.seno, tc.pl, tc.sno, st.val1, st.val2, st.date
FROM tc
LEFT JOIN st ON tc.seno = st.seno AND tc.pl = st.pl AND st.seno = 1304239136
WHERE tc.pl = 1
ORDER BY st.date DESC
This is the data returned:
I want to distinct by unique 'tc.sno', therefore I only want the first and third row returned as the middle date is earlier then the top one for the 'sno' 3. The 'sno' could always be different so I do not want to hardcode those numbers. I was trying to use 'GROUP BY' but it just picks the first value of the date, tried using 'HAVING' and combining select statements together but can't seem to get it working. (the val1 and val2 in row 2 could be random it is just a coincidence that they exact in this example)

Incorrect number of rows updated upon using Rand(Checksum(Newid()))

I have a SP which returns the count, i need to use this count and update random rows(count number of rows) in some other table , the count returned will always be lesser or equal than the number of rows available, so the random rows should always be available
below is the method i am using
i currently have 7 rows for the where clause and the count returned is also 7, but upon different tries, the below logic marks 1 for 5 or 6 rows and never 7, is it some drawback with using rand function?
is there any alternative to this?
EXEC #Randcount=dbo.[Usp_getcount]
UPDATE [mytable]
SET [output] = 1
WHERE [id] IN
(SELECT TOP (#Randcount)
[id] FROM [dbo].[mytable]
WHERE
[empid] = #empid AND [setId] = #setID
ORDER BY Rand(Checksum(Newid())))
any help would be appreciated.
There's no guarantee on how many times that subquery will be evaluated. If it was evaluated just once for the entire query, you'd expect to get exactly 7 rows updated. But if it's evaluated once per outer row, then it's effectively a coin toss for every row.
Simplest way that should work is to split this into two separate queries:
EXEC #Randcount=dbo.[Usp_getcount]
declare #IDs table (ID int not null)
insert into #IDs(ID)
SELECT TOP (#Randcount)
[id] FROM [dbo].[mytable]
WHERE
[empid] = #empid AND [setId] = #setID
ORDER BY Rand(Checksum(Newid()))
UPDATE [mytable]
SET [output] = 1
WHERE [id] IN
(SELECT ID from #IDs)

MySQL get interval records

Are there any solutions on MySQL script to filter the results with specific interval number.
For example, if I have 100,000 records in database and I'd like to get only the record number 1000, 2000, 3000, etc. (step by 1000).
I could do this on server side script by getting the entire results (e.g. 100,000) and use syntax like:
for($i=0, $i <= 100,000, $i = $i+1000) $filterResult[] = $record[$i];
However, as you may see, it would pull stress to the system as 100,000 records will need to generated first.
Are there any solutions that could complete from database script? Please note that, primary key may not start with 1 - 100,000 as the results based on some condition in where clause.
Your help would be really appreciated.
You can do:
SELECT *
FROM tbl
WHERE id % 1000 = 0
But it seems like you don't want to rely on the primary key value, but rather the row ranking of a result set.
In that case, you can do:
SELECT *
FROM (
SELECT *, #rn:=#rn+1 AS rank
FROM tbl
CROSS JOIN (SELECT #rn:=0) var_init
WHERE column1 = value AND
column2 = value
) a
WHERE a.rank % 1000 = 0
Where column1 = value AND column2 = value is just a placeholder for whatever filtration you're doing in your query.