I have a table with 6 columns (id, deviceID, athleteName, fieldName, valueTx, dateTime).
So far when I call my function getSensors it display all rows.
However I want to display at each update of the table only the latest row, depending on dateTime and deviceID columns.
I've never used store procedure, so I'm wondering if is it the best to do ? If not what do you suggest me to do ?
Many thanks in advance!!!
You don't need a stored procedure for this. A simple query:
select t.*
from t
where t.datetime = (select max(t2.datetime) from t t2 where t2.deviceID = t.deviceID);
If you are given a deviceID, you can get the most recent record as:
select t.*
from t
where t.deviceID = v_deviceID
order by t.datetime desc
limit 1;
Related
So I have two tables that displays values like a Facebook look-a-like feed. They both have a datetime column named date, but I want them to order them together by date DESC.
I think join is the correct way(?), but not quite sure. Can someone help me out?
Currently I have them in two different queries:
$status1 = "1";
$stmt1 = $link->prepare('
SELECT id
, ident_1
, ident_2
, date
, ident_1_points
, ident_2_points
FROM duel
WHERE active=?
ORDER
BY date
');
$stmt1-> bind_param('s', $status1);
and
$status2 = "OK";
$stmt2 = $link->prepare('SELECT id, ident, pp, date FROM sales WHERE status=? AND team IN (2, 3) ORDER BY date DESC LIMIT 20');
$stmt2->bind_param('s', $status2);
How should I do this?
If you want one continuous list containing data from both tables, and the whole thing ordered by date overall, then you might need a UNION query in a subquery, and then order the outer query, something like this:
SELECT *
FROM
(
SELECT id, ident_1, ident_2, date, ident_1_points, ident_2_points
FROM duel
WHERE active=?
UNION ALL
SELECT id, ident, pp, date, NULL, NULL
FROM sales
WHERE status=?
AND team IN (2, 3)
LIMIT 20
) list
ORDER BY date DESC
The requirement isn't 100% clear to be honest from your description (sample data and expected results always helps when asking SQL questions), but I think this is pretty close to what you need.
JOIN doesn't seem appropriate, unless you want a result set where items from each table are linked to each other by some common field, and you combine them such that you get all the columns side by side, showing the data from one table next to the data which matches from the other table.
If you're unsure, I suggest looking at tutorials / examples / documentation which show what JOIN does, and what UNION does.
I have the following database and want to delete the red ones because they are doubouled. So I have to check every row if another row is matching by pid, price, price_old, link and shop.
But how can I check that and how can I delete it then?
Maybe an easier way would be to generate a id from the values inside each row. So if the values inside a row would be equal also the id would be equal and who have only one value to compare with the other id's.
Is that a better way? - If yes, how can I do that?
Greetings!
Do the fact you have no way for get thi distinct row you could add uniqie id using
ALTER TABLE my_table
ADD id int NOT NULL AUTO_INCREMENT
Once done you could use not in where the id are not the min grouped by the value you need for define the duplication
delete from my_table
where id NOT in ( select min(id) from my_table
group by shop, link
)
The simplest way is to run a distinct query:
select distinct pid, price, price_old, link, shop
from t;
You can create a new table using into. That is the simplest way. Because all columns are the same, MySQL doesn't offer a simple method to delete duplicate rows (while leaving one of them).
However, it is possible that your current results are generated by a query. If so, you can just add select distinct to the query. However, it would be better to fix the query so it doesn't generate duplicates. If this is the case, then ask another question with sample data, desired results (as text, not an image), and the query you are currently using.
Test this first on a test table:
DELETE t1
FROM t t1, t t2
WHERE t1.id > t2.id AND t1.price = t2.price
AND t1.link = t2.link AND t1.shop = t2.shop
AND t1.price_old = t2.price_old;
Basically you are removing the one with the highest ID if those parameters are equal
select * from
(select pid, price, price_old, link ,
row_number() over(partition by pid, price, price_old, link, shop order by pid) as rank
from my_table) temp
where temp.rank = 1
This Query will group by all the columns first and rank them. Duplicate rows will have rank > 1. It does not matter we take first or second row as both are copy of each other. We just take rows with rank 1. Rows that are not duplicate will also be having rank 1 and hence won't be neglected.
One more way to this is by using union.
select * from my_table UNION select * from my_table
I have a database that stores a history of transactions, mostly comment updates. Therefore, I accept multiple records with the same ID.
What I need to do is pull in all of the records and display the most recent of each record.
Here is an example of 2 records with the same UID. The highlighted record is the most recent of the 2.
Here is one of the queries I attempted:
SELECT
uid
,voyage
,MAX(comments)
,MAX(edituser)
,MAX(editdate)
FROM
table
GROUP BY
uid
ORDER BY
uid
Here is the same UID that is returned:
If you'll notice, it is the most recent user and editdate, but it's not the most recent comment, which should be 'THIS IS A TEST COMMENT'.
I have tried several queries, but this is the closest I've gotten to returning the most recent of every record.
I tried this link: SQL Select record with most recent date
But I don't think I need to use any JOINS in this case, being that everything is in the same table.
How can I make this work?
With something like this, you are probably better off using sub-selects.
SELECT
t1.uid,
t1.voyage,
(SELECT comments FROM table t2 WHERE t2.uid = t1.uid AND t2.editdate = MAX(t1.editdate) LIMIT 1) as comments,
(SELECT edituser FROM table t2 WHERE t2.uid = t1.uid AND t2.editdate = MAX(t1.editdate) LIMIT 1) as edituser,
(SELECT editdate FROM table t2 WHERE t2.uid = t1.uid AND t2.editdate = MAX(t1.editdate) LIMIT 1) as editdate,
FROM table t1
GROUP BY t1.uid
ORDER BY t1.uid
Each sub-select narrows it down to the same uid, and then takes the one with the most recent editdate.
If that's what your desired output be then you should use MIN() instead like MIN(comments)
Change your order by to editdate by descending:
... ORDER BY editdate DESC
i would like to select an sql query from two different tables. but both tables are in the same database.
this is my sql code and "air, temp, humidity, mq2" are from one table known as the "pi_sensors_network" while "Dust" is from another table known as "pi_dust_sensor". may i know how to go about selecting air, temp, humidity, mq2, Dust from 2 different tables but the same database? Thanks!
on a side note, there is no relation between both the tables. i just want to fetch the data from two different tables.
$sql = "SELECT air, temp, humidity, mq2, Dust FROM pi_sensors_network ORDER BY time DESC LIMIT 1";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
Just use an alias for each table:
SELECT t1.air, t1.temp, t1.humidity, t1.mq2, t1.Dust As Dust1, t2.Dust As Dust2
FROM pi_sensors_network t1,
pi_dust_sensor t2
ORDER BY time DESC LIMIT 1";
You left a few things out in your schema description and query. Do you have a field in one of the tables that refers to the equivalent record in the other table (i.e. a foreign key)? If so, you can use a JOIN. You didn't mention which table has the time field.
Here is my stab at your desired query, but making assumptions on the unanswered questions. I assumed that you had a field pi_sensors_network.id that is a primary key for the pi_sensors_network table. I also assumed that there was a field pi_dust_sensor.fkid that connected the rows in the pi_dust_sensor table with the rows in the pi_sensors_network table.
SELECT air, temp, humidity, mq2, Dust
FROM pi_sensors_network INNER JOIN
pi_dust_sensor ON pi_sensors_network.id = pi_dust_sensor.fkid
ORDER BY time DESC LIMIT 1
Hopefully that will point you in the right direction. If you can answer my questions, I will be happy to update my answer.
you can combine data of two table in one object and can use after that how you want the output look like:
SELECT *
(
SELECT air, temp, humidity, mq2, '' As Dust,[time]
FROM pi_sensors_network
union all
select '' as air, '' as temp, '' as humidity, '' as mq2, Dust As Dust,[time]
from pi_dust_sensor
)base
ORDER BY [TIME] DESC
Let's say I have a table with the following columns:
p_id
userid
points
Let's say these columns have over 5000 records. So we actually have users with points. Each user has an unique row for their point record. Imagine that every user can get points on the website by clicking somewhere. When they click I update the database with the points they get.
So we have a table with over 5000 records of people who have points, right? Now I would like to order them by their points (descending), so the user with the most point will be at the top of the page if I run a MySQL query.
I could do that by simply running a query like this:
SELECT `p_id` FROM `point_table` ORDER BY `points` DESC
This query would give me all the records in a descending order by points.
Okay, here my problem comes, now (when it is ordered) I would like to display each user which place are they actually. So I'd like to give each user something like this: "You are 623 of 5374 users". The problem is that I cannot specify that "623" number.
I would like to run a query which is order the table by points it should "search" or count the row number, where their records are and than return that value to me.
Can anyone help me how to build a query for this? It would be a really big help. Thank you.
This answer should work for you:
SET #rank=0;
SELECT #rank:=#rank+1 AS rank, p_id FROM point_table ORDER BY points DESC;
Update: You might also want to consider to calculate the rank when updating the points and saving it to an additional column in the same table. That way you can also select a single user and know his rank. It depends on your use cases what makes more sense and performs better.
Update: The final solution we worked out in the comments looked like this:
SELECT
rank, p_id
FROM
(SELECT
#rank:=#rank+1 AS rank, p_id, userid
FROM
point_table, (SELECT #rank := 0) r
ORDER BY points DESC
) t
WHERE userid = intval($sessionuserid);
Row number after order by
SELECT ( #rank:=#rank + 1) AS rank, m.* from
(
SELECT a.p_id, a.userid
FROM (SELECT #rank := 0) r, point_table a
ORDER BY a.points DESC
) m
For some reason the accepted answer doesn't work for me properly - it completely ignores "ORDER BY" statement, sorting by id (primary key)
What I did instead is:
SET #rn=0;
CREATE TEMPORARY TABLE tmp SELECT * FROM point_table ORDER BY points DESC;
SELECT #rn:=#rn+1 AS rank, tmp.* FROM tmp;
Add a new column for position to the table. Run a cron job regularly which gets all the table rows ordered by points and then update the table with the positions in a while loop.