How can I get last inserted values for a user? - mysql

I have this MYSQL table...
+----+---------+-----------+---------------+------------+---------------------+
| id | user | val1 | val2 | val3 | last_modified_date |
+----+---------+-----------+---------------+------------+---------------------+
| 1 | 0001 | 1 | 1 | 1 | 2014-03-31 16:53:29 |
| 2 | 0100 | 1 | 1 | 1 | 2014-04-01 10:32:50 |
| 3 | 0200 | 1 | 0 | 0 | 2014-04-01 10:34:13 |
| 4 | 0200 | 1 | 1 | 1 | 2014-04-01 14:43:47 |
+----+---------+-----------+---------------+------------+---------------------+
What I'm trying to achieve is getting all the last (in order of time) set of values created for the users.
In the example given we insert 0 for user 0200 but after 4 hours we insert 1. I want to be able to get the last value inserted (1).
I have this query:
select *
from table
where val3 = 1
group by user
order by last_modified_date desc;
And a more generic one
select * from table group by user order by last_modified_date desc;
These queries seems to be working fine for the example table. Are they correct for every case? How can I tell "select all the users that have val3 = 1 as their last inserted value"?

You can use one of these two methods:
Option 1 - get the last record for each user and filter for t.val3:
SELECT t.*
FROM table t
JOIN (
SELECT MAX(last_modified_date) as last_modified, user
FROM table
GROUP BY user
) as tt ON t.user = tt.user AND t.last_modified_date = tt.last_modified_date
GROUP BY user
HAVING val3 = 1
Option 2 - get all the records for t.val3 = 1 and remove those which are not last:
SELECT t.*
FROM table t
LEFT JOIN table tt ON tt.user = t.user AND tt.last_modified_date > t.last_modified_date
WHERE t.val3 = 1
AND tt.id IS NULL

Try this
select * from table as t1
where val3 = 1
and last_modified_date =
(select max(last_modified_date) as last_modified_date from table as t2
where t1.user=t2.user and t2.val3 = 1 );

Related

I need to get the average for every 3 records in one table and update column in separate table

Table Mytable1
Id | Actual
1 ! 10020
2 | 12203
3 | 12312
4 | 12453
5 | 13211
6 | 12838
7 | 10l29
Using the following syntax:
SELECT AVG(Actual), CEIL((#rank:=#rank+1)/3) AS rank FROM mytable1 Group BY rank;
Produces the following type of result:
| AVG(Actual) | rank |
+-------------+------+
| 12835.5455 | 1 |
| 12523.1818 | 2 |
| 12343.3636 | 3 |
I would like to take AVG(Actual) column and UPDATE a second existing table Mytable2
Id | Predict |
1 | 11133
2 | 12312
3 | 13221
I would like to get the following where the Actual value matches the ID as RANK
Id | Predict | Actual
1 | 11133 | 12835.5455
2 | 12312 | 12523.1818
3 | 13221 | 12343.3636
IMPORTANT REQUIREMENT
I need to set an offset much like the following syntax:
SELECT #rank := #rank + 1 AS Id , Mytable2.Actual FROM Mytable LIMIT 3 OFFSET 4);
PLEASE NOTE THE AVERAGE NUMBER ARE MADE UP IN EXAMPLES
you can join your existing query in the UPDATE statement
UPDATE Table2 T2
JOIN (
SELECT AVG(Actual) as AverageValue,
CEIL((#rank:=#rank+1)/3) AS rank
FROM Table1, (select #rank:=0) t
Group BY rank )T1
on T2.id = T1.rank
SET Actual = T1.AverageValue

How to delete unknown number last record (on condition)?

Could you please tell me how to delete unknown number last record (on condition)?
For example, in this situation I want to delete record with id: 6 to 10.
Note: this table and records is not constant.
+----+-----+---------+
| id | url | emailid |
+----+-----+---------+
| 1 | 10 | 1 |
| 2 | 20 | 0 |
| 3 | 30 | 2 |
| 4 | 40 | 0 |
| 5 | 50 | 10 |
| 6 | 60 | 0 |
| 7 | 70 | 0 |
| 8 | 80 | 0 |
| 9 | 90 | 0 |
| 10 | 100 | 0 |
+----+-----+---------+
Thanks...
It seems that you want to delete the last set of records where all the values are 0. This is a bit of a pain. You can find the minimum such id as:
select min(t.id)
from table t
where t.emailid = 0 and
not exists (select 1 from table t2 where t2.id > t.id and t2.emailid <> 0);
The logic is: find all rows where emailid is 0 and there are no subsequent emailids that are not zero.
You can put this into a delete using join:
delete t
from table t cross join
(select min(t.id) as first0id
from table t
where t.emailid = 0 and
not exists (select 1 from table t2 where t2.id > t.id and t2.emailid <> 0)
) tmin
where t.id >= tmin.first0id;
You can use between keyword in your query like this
delete from yourtable where id BETWEEN 6 AND 10
use this query
delete from your_table where id between 6 AND 10
for not being constant you can first store start and end values in variable and then pass in query,example(in php)
$start = 6 ;
$end = 10;
query
"delete from your_table where id between $start AND $end"

MySQL select from specific ID until match condition

Given this table:
+----+-----------+--------+
| id | condition | values |
+----+-----------+--------+
| 1 | a | 1 |
+----+-----------+--------+
| 2 | a | 2 |
+----+-----------+--------+
| 3 | a | 3 |
+----+-----------+--------+
| 4 | a | 4 |
+----+-----------+--------+
| 5 | b | 5 |
+----+-----------+--------+
| 6 | b | 6 |
+----+-----------+--------+
How can I get a new table that begins on id=3 (including) and goes until condition = b (excluding):
+----+-----------+--------+
| id | condition | values |
+----+-----------+--------+
| 3 | a | 3 |
+----+-----------+--------+
| 4 | a | 4 |
+----+-----------+--------+
added fiddle: http://sqlfiddle.com/#!2/9882f7
Basically I want a table between a matching first condition (over a specific column - id) and a second one (over a different column - condition)
You need to stop thinking of SQL data as having any order. Think of SQL data in sets; you have to search by values, not by positions.
SELECT t1.*
FROM t AS t1
JOIN (
SELECT MIN(id) AS id FROM t
WHERE id >= 3 AND `condition` = 'b'
) AS t2
WHERE t1.id >= 3 AND t1.id < t2.id
ORDER BY t1.id
Something like this:
select t.*
from table t
where id >= 3 and id < (select min(t2.id) from table t2 where t2.condition = 'b');
EDIT:
This query works fine on the SQL Fiddle:
select t.*
from t
where id >= 3 and id < (select min(t2.id) from t t2 where t2.condition = 'b');
If I understand what you are asking for, I believe this will work for you:
SELECT id, condition, values
FROM tableName
WHERE id > 2
AND condition != b
ORDER BY id
I hope that works for you.

MySQL fetching rows based on condition within condition

I have the following below
---------------------------------
| Id | Value | Flag |
---------------------------------
| 1 | 23 | 0 |
---------------------------------
| 1 | 24 | 1 |
---------------------------------
| 2 | 30 | 0 |
---------------------------------
I require a query, which should fetch the last two rows. The condition here is IF two rows have the same Id then the output should fetch the row which has flag = 1 . Where as If there is only one row for an Id, then the row with Flag = 0 should be fetched. Thus the output for the given requirement will be
---------------------------------
| 1 | 24 | 1 |
---------------------------------
| 2 | 30 | 0 |
SELECT
*
FROM yourTable yt1
WHERE Flag = (SELECT MAX(Flag) FROM yourTable yt2 WHERE yt1.Id = yt2.Id)
GROUP BY Id
Other answers looks correct to me. This is a different approach:
SELECT t1.*
FROM
yourtable t1 LEFT JOIN yourtable t2
ON t1.Id = t2.Id AND t1.Flag=0 AND t2.Flag=1
WHERE
t2.Id IS NULL
Please see fiddle here.
I prefer an uncorellated approach...
SELECT x.*
FROM my_table x
JOIN
( SELECT id,MAX(flag) max_flag FROM my_table GROUP BY id ) y
ON y.id = x.id
AND y.max_flag = x.flag;

update other rows in same table when one row is deleted

table Lets call it test
----------------------------
| id | catid | value |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 1 | 3 |
| 5 | 1 | 4 |
| 6 | 1 | 5 |
| 7 | 2 | 2 |
----------------------------
Suppose i deleted the 2nd row from table. Now the table will become:
----------------------------
| id | catid | value |
| 1 | 1 | 1 |
| 3 | 2 | 1 |
| 4 | 1 | 3 |
| 5 | 1 | 4 |
| 6 | 1 | 5 |
| 7 | 2 | 2 |
----------------------------
So in catid1, there is no value 2. so the values will become, 1,3,4,5,.... so far so on....
Goal I need to update the values as subtracting 1 from their previous value so that the continuity is maintined (all values goes one up if the condition is met i.e. if bgger than the deleted value).
CODE
After delete, i am trying to perform an update query.
UPDATE `test`
SET `value` =
(
SELECT t.param FROM (
SELECT `value`-1 AS param
FROM `test`
WHERE
`catid` = 1 AND `value` > 2
) AS t
)
WHERE
`catid` = 1
AND `value` > 2
Now, the most inner query will return all the rows which has value >2 where as the update expects a scalar value of string or numeric.
So the question is how can i return the value in the innermost query with respect to what row is update query targeting?
e.g. If update query is trying to update the row with id 4, the innermost query will retreive the value column with the same row id only and give it back to outer query (after subtracting 1).
Is there any alternative approach in this?
JOIN that table with this subquery like this:
UPDATE test t1
INNER JOIN
(
SELECT
id, catid, value - 1 AS value
FROM test
WHERE catid = 1
AND value > 2
) AS t2 ON t1.id = t2.id
SET t1.value = t2.value;
SQL fiddle demo.
But there is no need for this subquery, you can do this directly like this:
UPDATE test t1
SET value = value - 1
WHERE catid = 1
AND value > 2;
However, You might need to fix that column id to match those values like this:
UPDATE test AS t1
INNER JOIN
(
SELECT
*,
(#rownum := #rownum + 1) AS newID
FROM test, (SELECT #rownum := 0) AS t
ORDER BY Id
) AS t2 ON t1.id = t2.id
SET t1.id = t2.newId,
t1.value = CASE
WHEN t1.catid = 1 AND t1.value > 2 THEN t2.value - 1
ELSE t1.value
END;
Updated SQL Fiddle Demo.