I have three columns in my table the name of the column is date_time,total,sub and i want to update the existing sub column by subtracting previous row total value and next row total value by order of date_time column using mysql.I don't know how to achieve this result.The data are given below
date_time total sub
2019-03-07 12:32:10 50 0
2019-03-07 12:34:22 60 0
2019-03-07 12:37:17 75 0
2019-03-07 12:44:10 100 0
i want to update the above record as
date_time total sub
2019-03-07 12:32:10 50 0
2019-03-07 12:34:22 60 10
2019-03-07 12:37:17 75 15
2019-03-07 12:44:10 100 25
Please guide me to achieve this result
Try this code
update your_table_name U left join
(select
(CASE
WHEN #pev_row_value = 0 THEN 0
ELSE (`your_table_name `.total - #pev_row_value)
END) as sub_result,
(#pev_row_value := `your_table_name `.total ) as current_row,
users.*
FROM `your_table_name ` cross join
(select #pev_row_value := 0) params
order by date_time asc) A on U.date_time=A.date_time
set U.sub = A.sub_result
Hopefully it will be work fine. In CASE WHEN ELSE statement set the sub_result for update and pev_row_value stored the value of previous row of total column value. Then whole regenerated value worked as a table which new name is A and update the final value with join the new table A.
Thanks
Related
I have a table with the structure below with name table1
sid userid date result
1 169110 2020-01-03 (null)
2 178662 2020-01-06 (null)
3 165381 2020-01-07 (null)
5 368031 2020-01-08 (null)
7 163626 2020-01-09 (null)
Now I need to send each row values of cft.userid and cft.date to a mysql query (query is below) which gives the value of the result for each row
UPDATE collision_fact_table cft
SET cft.on_time_completion = (
SELECT DISTINCT
CONCAT(ROUND(NULLIF(SUM(facttable.compliant), 0) / NULLIF(SUM(facttable.Occurences), 0) * 100), '%') AS `Percentage Completed`
FROM fd_dw.ComplianceFactTable facttable
WHERE (CAST(facttable.`CourseModule_dueDateID` AS date) - cft.collision_date) <= 0
AND facttable.UserLicenseInUsing = 1
AND (facttable.`CourseModule_dueDateID` > 0)
AND facttable.UserId = cft.userid
GROUP BY facttable.`UserID`);
For example, when i send first row values of userid 169110 and date value to the above query, i will get result as 69 and i need to update 69 to the table1 like below
sid userid date result
1 169110 2020-01-03 69
Similarly it should iterate for all the rows and table1 should get updated like below
sid userid date result
1 169110 2020-01-03 69
2 178662 2020-01-06 55
3 165381 2020-01-07 64
5 368031 2020-01-08 48
7 163626 2020-01-09 56
But when i tried to execute the update query, its giving me error Unknown column 'cft.date' in field list
Please anyone help me
I think you basically want a correlated subquery:
update table1 t1
set result = (
select cd.result
from ...
where
cd.ScheduleDateID <= t1.date
and cd.CourseModuleComplete_DateID <= t1.date
and cd.UserId = t1.userid
)
You don't give much details about the subquery itself. It is critical that it should return one row, and one row only:
if it returns no rows, then the result of the corresponding row in table1 will be set to null (regardless of its original value) - this might, or might not be what you want
if it returns more than one row, then the query will error
I have two tables
Table_1 : Routes_Day_plan
Date Status_Id
------------------------
2019-06-09 1
2019-06-10 2
2019-06-09 2
2019-06-11 3
2019-06-14 4
2019-06-14 6
2019-06-15 8
Table_2 : Codes
id code
-------
1 Leave
2 Half_leave
3 Holiday
4 Work
5 Full_Hours
Now my task is to count week wise from table 1 where code (from second table) = Leave,Half_leave,work and than also show the sum , and where date not found show 0 , i write this query it's return data but not empty dates can someone please help ,
My Query:
select COUNT(*) as available, DATE(date)
from Table_1
where status_id in (
select id from codes
where code in ('Leave','Half_leave','work'))
AND DATE(date) >= DATE('2019-06-09') AND DATE(date) <= DATE('2019-06-16')
group by date
UNION ALL
SELECT COUNT(date), 'SUM' date
FROM Table_1
where status_id in (
select id from codes
where code in ('Leave','Half_leave','work'))
AND DATE(date) >= DATE('2019-06-09') AND DATE(date) <= DATE('2019-06-16')
Result Something Like ,
available Dates
------------------------
5 2019-06-09
2 2019-06-10
3 2019-06-11
3 2019-06-12
2 2019-06-14
2 2019-06-15
17 SUM
I want like this
available Dates
------------------------
5 2019-06-09
2 2019-06-10
3 2019-06-11
3 2019-06-12
0 2019-06-13
2 2019-06-14
2 2019-06-15
17 SUM
Your best bet here would be to have a Date Dimension/Lookup table which contains pre-populated dates for the entire year. By joining your record table to this lookup, you essentially allocate your data to each date that actually exist (ex. 2019-06-13) and if your data is not found in the lookup, you will find a null in that field.
The Count function will count a null as a 0. Just make sure you group on the date field from your lookup table and not from your record table.
Make a table, a date dimension that contains all the dates value, from beginning to end. Like this:
Set EndDate = '2099-01-01';
Set RunDate = '1900-01-01';
WHILE RunDate <= EndDate DO
insert into dim_date
(`DATE`)
select
RunDate as DATE
;
Set RunDate = ADDDATE(RunDate,1);
END WHILE;
Create temporary table with dim_date left join Routes_Day_plan and set Status as 0 maybe for record that dont match. Use this temporary table then instead of Routes_Day_plan in your queries.
I have a table with the columns : id, status, value.
id status value
-- ------ -----
1 10 100
2 10 100
3 10 60
4 11 20
5 11 15
6 12 100
7 12 50
8 12 50
I would like to get the id and value of the first and second highest valued rows, from each status group. My table should have the following columns:
status, id of the first highest value, first highest value, id of second highest value, second highest value.
I should get:
status 1stID 1stValue 2ndID 2ndValue
------ ----- -------- ----- --------
10 1/2 100 2/1 100
11 4 20 5 15
12 6 100 7/8 50
I tried all kinds of solutions, but I couldn't find a solution for same-value 1st s (two rows with the same value, which happened to be the highest in that status group) or same-value seconds.
For example, in case of two rows sharing the highest value in their status group, this not-so-elegant query will return two rows with the same status, different 1sts and same 2nd:
SELECT 2nds.status, 1sts.id AS "1stID",1sts.value AS "1stValue",
2nds.id AS "2ndID",2nds.value AS "2ndValue"
FROM
(SELECT v.* FROM
(SELECT status, MAX(value) AS "SecMaxValue" FROM table o
WHERE value < (SELECT MAX(value) FROM table
WHERE status = o.status
GROUP BY status) AS m
INNER JOIN table v
ON v.status = m.status AND v.value = m.SecMaxValue) AS 2nds
INNER JOIN
(SELECT v.* FROM
(SELECT status, MAX(value) AS maxValue FROM table
GROUP BY status) AS m
INNER JOIN table v
ON v.status = m.status AND v.value = m.MaxValue) AS 1sts
ON 1sts.status = 2nds.status ;
This query will give me:
status 1stID 1stValue 2ndID 2ndValue
------ ----- -------- ----- --------
10 1 100 3 60
10 2 100 3 60
11 4 20 5 15
12 6 100 7 50
12 6 100 8 50
To conclude, I would like to find a solution in which:
a. if there are two rows with the highest value the query puts the details one of them in the column of the 1st and the details of other in 2nd (no mather which)
b. if there are two rows with the second highst value it puts the highest in its place and one of the seconds in the second place.
Is there a way to change the query above? someone has a nicer solution?
I came across several 1st and 2nd queries but they had the same problem - for example this solution: Finding the highest n values of each group in MySQL. it does not deliver 1st and 2nd in the same row, but the main problem it provides only one of the firsts.
Thanks
After spent a lot of time, finally I found a solution for above problem. Please try it out:
select 1st.status as Status,
SUBSTRING_INDEX(1st.id,'/',1) as 1stID,
1st.value as 1stValue,
(case when locate('/',1st.id) > 0 then SUBSTRING_INDEX(1st.id,'/',-1)
else 2nd.id
end) as 2ndID,
(case when locate('/',1st.id) > 0 then 1st.value
else 2nd.value
end) as 2ndValue
from
(
(select status, SUBSTRING_INDEX(Group_concat(id separator '/'),'/',2) as id,value
from t1
where (status,value) in (select status,value
from t1
group by status
having max(value))
group by status) 1st
inner join
(select status,id,value
from t1
where (status,value) not in (select status,value
from t1
group by status
having max(value))
group by status,value
order by status,value desc) 2nd
on 1st.status = 2nd.status)
group by 1st.status;
Just replace t1 with your tablename and it should work like a charm.
Click here for Updated Demo
If you have any doubt(s), feel free to ask.
Hope it helps!
In MySQL, I want to find all the rows where the value of a column went to 0 after a specific date.
So, given the data:
cat value date
a 95 2015-09-01
a 78 2015-10-01
a 0 2015-11-01
a 0 2015-12-01
b 129 2015-09-01
b 230 2015-10-01
b 201 2015-11-01
b 140 2015-12-01
In this case, I want to run a query that asks:
Which categories have 0 value after 10/1/2015 and had a positive value before 11/1/2015?
The result should show category "a".
I suspect is a nested select statement, but haven't quite figured it out.
select * from yourTable where value = 0 and date > '2015-10-01' and cat in (
select distinct cat where value > 0 and date < '2015-11-1'
)
Explanation: you can split the query to two parts - the inner query with the in statement is in charge of getting the cat ID's that were positive before 11/1/15, and the where value = 0 and date > '2015-10-01' will give you those that are 0 after 10/1/15
Building off what Nir Levy said, if you only want the category to be returned, you can select just the distinct values for cat:
SELECT DISTINCT cat
FROM stack_test.your_table
WHERE value = 0 AND date > '2015-10-01' AND
cat IN (SELECT cat FROM stack_test.mysql_rows WHERE value > 0 AND date < '2015-11-01');
I have a table called 'ratings' which contains an index which is a unique ascending number, ProductId which is a product code, rate1 to rate5 are the number of times each product has recieved a 1 or 5 star rating by a customer aveRate is the average rating for each product and lastSubDate should be the timestamp of when the last review for each product was submitted but it's currently empty.
id ProductId rate1 rate2 rate3 rate4 rate5 aveRate lastSubDate
18 9996637 0 0 0 0 1 5 0000-00-00 00:00:00
26 9996628 1 0 0 0 0 1 0000-00-00 00:00:00
34 9996618 0 0 0 1 0 4 0000-00-00 00:00:00
36 9996614 5 0 0 0 0 1 0000-00-00 00:00:00
48 9996592 5 0 1 0 3 3 0000-00-00 00:00:00
66 9996566 0 0 0 1 3 5 0000-00-00 00:00:00
In another table I have called 'last_rate_date' I have ProductId and the date the product was last rated under lastSubDate. In this table the Product Id's can appear several times as per the example as each row represents a time a review was submitted by a customer.
ProductId lastSubDate
9996665 2009-05-22 19:45:05
9996665 2009-08-06 11:30:07
9996665 2010-11-10 08:30:17
9996665 2011-06-10 09:15:47
9996665 2011-06-12 05:15:39
My questions is how can I modify the first table 'ratings' using SQL to insert the last time a product was reviewed under the 'lastSubDate' using the second table 'last_rate_date' to lookup the productId and the date bearing in mind each ProductId may appear mutiple times in this seconds table with differen't dates.
This needs to be one as a one off table modification to the first table. Adter this is done I will amend the script which adds data to ratings table to always add a timestamp in the future when it's updated.
You can get most recent dates for each "ProductId" using the query below:
Select ProductId, MAX(lastSubDate)
From last_rate_date
Group By ProductId
This will produce each ProductId that appears in the second table, along with the latest date (using the MAX function). The Group By clause is needed to define what the aggregation is run against.
To further solve your problem, you can insert this Select statement into an Update statement like so:
UPDATE ratings a
INNER JOIN (
Select ProductId, MAX(lastSubDate) as finalLastSubDate
From last_rate_date
Group By ProductId ) b
ON a.ProductId = b.ProductId
SET a.lastSubDate = b.finalLastSubDate
You can use the timestamp with CURRENT_TIMESTAMP default
or you can add the date on the insert.
$date = date ("m-Y-d, H: i: s")