I have a table of water readings. I need to know how much was consumed by each property based on 2 given dates.
Below is how my data looks like.
How can I create a mysql query which will
ask what dates (say between 08/16/2021 and 08/12/2021) to get the difference in readings
compute the difference
enter results in a new column "consumed between 8/12 and 8/16".
I am very new with mysql and your assistance is highly appreciated.
Thanks
In this query, you can replace your start and end dates with your application variables or stored procedure parameters.
Find my step-by-step queries here -> db<>fiddle
Try this -
set #v_start_date = '2021-08-12';
set #v_end_date = '2021-08-16';
SELECT
wr_start_table.Unit_No,
wr_start_table.Date,
wr_start_table.Reading,
wr_end_table.Date,
wr_end_table.Reading,
wr_end_table.Reading - wr_start_table.Reading AS difference_in_reading
FROM
(
SELECT
wr_start_unit.*
FROM
water_reading wr_start_unit
INNER JOIN (
SELECT
wr.Unit_No,
min(wr.Date) AS start_date
FROM
water_reading wr
WHERE
wr.Date >= #v_start_date
GROUP BY
wr.Unit_No) AS wr_start ON
wr_start.Unit_No = wr_start_unit.Unit_No
AND wr_start.start_date = wr_start_unit.Date) AS wr_start_table,
(
SELECT
wr_end_unit.*
FROM
water_reading wr_end_unit
INNER JOIN (
SELECT
wr.Unit_No,
max(wr.Date) AS end_date
FROM
water_reading wr
WHERE
wr.Date <= #v_end_date
GROUP BY
wr.Unit_No) AS wr_end ON
wr_end.Unit_No = wr_end_unit.Unit_No
AND wr_end.end_date = wr_end_unit.Date) AS wr_end_table
WHERE
wr_start_table.Unit_No = wr_end_table.Unit_No;
Related
I've got a table called scheduleData which contains the following columns:
ID | CREATED (time stamp) | CLIENT | PROJECT | RESOURCE | EFFORT | WEEK (date)
The data comes straight from an "Excel schedule", hence it's not relational.
Each row represents a resource that's booked on a particular project in a particular week.
Each time the data is exported from excel much of the data is duplicated, so i'm only ever interested in the latest data set based on the CREATED column.
For each project I want to return a row showing the MIN and MAX week, within the latest data set (based on CREATED) to essentially determine the start and end date for each project.
Found a the example below which from the description seems to do the trick but I get error message when i try to execute it
SELECT t.* FROM scheduleData t
JOIN
( SELECT project, MIN(week) minVal
FROM scheduleData GROUP BY project
) t2
ON t.week = t2.minVal AND t.project = t2.project;
Adapted the following example: Select min value per item in MySQL
Cheers,
Mikael
realized when I looked at this with fresh eyes that I was just being a bit thick, and that my question was a bit rubbish. Anyway, I've managed to adapt the query to do exactly what I want, i.e. return the max and minimum value (in this instance a date) for any given unique item, in this case a project.
The SQL for this is as follows:
SELECT DISTINCT(t.week), t.project, t.client
FROM scheduleData t
JOIN
( SELECT project, MIN(week) AS minVal, MAX(week) as maxVal
FROM scheduleData GROUP BY project) t2
ON ( t.date = t2.minVal OR t.date = t2.maxVal) AND t.project = t2.project
table name is data.
Columns - 'date', 'location, 'fp, 'TV'
Under date I will have multiple different dates but each date has a number of rows with the same date. Same with location.
I am trying to work out the average of TV for every time the date and location are the same and fp = 1, and insert the result into a new column called avgdiff
So I might have a number of rows with the date 2016-12-08 and location LA, with different numbers under fp and TV. So when the date is 2016-12-08 and location is LA, fp might equal 1, 4 times, and TV for those 4 rows might be 7.4, 8.2, 1, -2. So the avg will be 3.65.
I think I need to use avg and count functions with conditions but I am having a lot of trouble with this. I hope this makes sense.
Thanks
You can query for the average using a GROUP BY:
SELECT `date`, `location`, AVG(`TV`) AS `avgtv`
FROM `data`
WHERE `fp` = 1
GROUP BY `date`, `location`
To update another table with your computed averages (which I strongly recommend against), you can use an UPDATE...JOIN with the above as a subquery:
UPDATE ratings r
JOIN ( /* paste above query here */ ) t
ON t.date = r.date AND t.location = r.location
SET r.avgtv = t.avgtv
If, for any reason, you cannot avoid storing aggregated data in the same table (thereby introducing redundancy and possibly incorrect/not up to date values), do an update statement of the following form:
update data,
(select t2.location, t2.date, avg(t2.TV) as avgTV2
from data t2
where t2.fp = 1
group by t2.location, t2.date) aggValues
set avgTV = avgTV2
where data.location = aggValues.location
and data.date = aggValues.date
and data.fp = 1
This query below selects all rows that have a row with the same father registering 335 days or less since earlier registration. Is there a way to edit this query so that it does not eliminate the duplicate row in the output? I need to see all instances of the registration for that father within 335 days of each other.
SELECT * FROM ymca_reg a later
WHERE NOT EXISTS (
SELECT 1 FROM ymca_reg a earlier
WHERE
earlier.Father_First_Name = later.Father_First_Name
AND earlier.Father_Last_Name = later.Father_Last_Name
AND (later.Date - earlier.Date < 335) AND (later.Date > earlier.Date)
My current query is:
SELECT ymca_reg.* FROM ymca_reg WHERE (((ymca_reg.Year) In (SELECT Year FROM ymca_reg As Tmp
GROUP BY Year, Father_Last_Name, Father_First_Name
HAVING Count(*)>1
And Father_Last_Name = ymca_reg.Father_Last_Name
And Father_First_Name = ymca_reg.Father_First_Name)))
ORDER BY ymca_reg.Year, ymca_reg.Father_Last_Name, ymca_reg.Father_First_Name
This query does return all the duplicates for review correctly, but it's terribly slow because it doesn't use a join and as soon as I add the date criteria it only returns the later row. Thanks.
I think you want something like this:
SELECT *
FROM ymca_reg later
WHERE EXISTS (SELECT 1
FROM ymca_reg earlier
WHERE earlier.Father_First_Name = later.Father_First_Name AND
earlier.Father_Last_Name = later.Father_Last_Name AND
abs(later.Date - earlier.Date) < 335 and
later.Date <> earlier.Date
);
This should return all records that have such duplicates. Note that "later" and "earlier" are no longer really apt descriptions, but I left the names so you can see the similarity to your query.
I have a table which logs all "check-ins" into a system. I want to count all "check-ins" from an user for the current day, but there's the problem that sometimes users check-in like two or three times by mistake in one minute. So I just want to count all entries with a gap from at least two minutes
My current command looks like:
"SELECT event_datetime, LEFT(tag_uid,8) AS tag_uid, count(*) as anzahl FROM events WHERE date(event_datetime) = curdate() GROUP BY tag_uid"
So I only want to count it if the gap between event_datetime is at least two minutes grouped by the tag_uid (the user)
Any ideas how to solve that?
first, you need to calculate the gap for each tag_uid and then you can set conditions as you wish. To calculate the gap you need to have a nested select commands which will get the "first checkIn" and "last checkIn" using min and max command. Use the "timediff" to calculate the time gap.
NOTE: i haven't tried the code, also I've added the select commands so you can see the values to find Errors.
the code would look similar to this:
SELECT
tbl_outer_events.event_datetime,
LEFT(tbl_outer_events.tag_uid,8) AS tag_uid,
count(tbl_outer_events.tag_uid) as anzahl,
(select min(event_datetime) from tbl_events as T1 where ( (t1.tag_uid = tbl_outer_events.tag_uid)) and (date(t1.event_datetime) = curdate()) )as `first_checkin`,
(select max(event_datetime) from tbl_events as T1 where ( (t1.tag_uid = tbl_outer_events.tag_uid)) and (date(t1.event_datetime) = curdate()))as `last_checkin`,
(select TIMEDIFF(max(event_datetime), min(event_datetime)) from tbl_events as T1 where ( (t1.tag_uid = tbl_outer_events.tag_uid)) and (date(t1.event_datetime) = curdate())) as `interval`
FROM events as tbl_outer_events
WHERE ((date(event_datetime) = curdate())
AND (select TIMEDIFF(max(event_datetime), min(event_datetime)) from tbl_events as T1 where ( (t1.tag_uid = tbl_outer_events.tag_uid)) and (date(t1.event_datetime) = curdate())) >= '00:20:00')
GROUP BY tag_uid;
PS: please provide us with sample data or desired outcome. it will help us and you to understand the issue.
SET #startdate = (select LOG_TIME from log.time where sender='Japan' and receiver ='USA' and code=158);
SET #enddate = (select LOG_TIME from log.time where sender='Japan' and receiver ='USA' and code=189);
select * from log.time where DATEDIFF(minute, #startdate, #enddate) >= 10;
Here I want to use 2 variables (#startdate and #enddate) which are populated with multiple entries coming from the select queries used .
And for the last line , I want the select query to return a list of records where the DATEDIFF function is greater than or equal to 10 minutes by using these 2 variables with multiple values .
P.S I am using the Squirrel SQL Client 2.3 )
The issue is I have no idea if it is possible to use multiple values for variables.
Also please advise or provide any solution to the above issue such that the query works in the end.
You can't use variables this way.
Now it's hard to tell for sure not seeing your table schema and sample data but you should be able to do what you want using JOIN with a query like this
SELECT l1.*
FROM log.time l1 JOIN log.time l2
ON l1.sender = l2.sender
AND l1.receiver = l2.receiver
AND l1.code = 158
AND l2.code = 189
WHERE l1.sender = 'Japan'
AND l1.receiver = 'USA'
AND DATEDIFF(minute, l1.log_time, l2.log_time) >= 10
If you were to provide a table schema, sample data and desired output, then it'll be possible to test your query