Let's say I have a table like this:
ID Type Itemcount DateTime
1 2 4 2018-05-05
2 1 10 2019-09-09
3 2 4 2018-05-05
4 1 10 2019-09-09
How to get the average amount of items of type 1 to exist by the datetime (grouped per week)
and I should go for one year back?. What is the max amount of items?
My solution :
set #totalitemssAllTypes = (SELECT count(Itemcount)
FROM db_dev.products
where Datetime >= '2018-06-12 00:10:00.000000');
SELECT CONCAT(YEAR(Datetime ), '/',MONTH(Datetime ), '/', WEEK(Datetime )), (count(LotCount)/#totalitemssAllTypes )
FROM db_dev.products
where Datetime >= '2018-06-12 00:10:00.000000' and
Type = 1
GROUP BY WEEK(Datetime);
Please help thank you
One option would use the WEEK() function to aggregate:
SELECT
WEEK(DateTime) AS week,
AVG(Itemcount) AS item_avg
FROM db_dev.products
WHERE
Type = 1 AND
DateTime >= DATE_SUB(NOW(), INTERVAL 1 YEAR)
GROUP BY
WEEK(DateTime);
It should be noted that WEEK() may not number the weeks from 1 onward starting with the earliest week.
Related
I have a table which looks like this:
start_date end_date id value
05.10.2010 07.10.2010 1 5
11.12.2010 15.12.2010 2 10
01.01.2023 3 6
I want to write sql query that will multiply number of days from start_date to end_date for each id with its value. So desired result is:
id sum_value
1 15
2 50
3 60
its 15 because there are 3 days (from 05.10.2010 to 07.10.2010) for id 1 and value is 5
its 50 because there are 5 days (from 11.12.2010 to 15.12.2010) for id 2 and value is 10
its 60 because there are 10 days (from 01.01.2023 to current date) for id 3 and value is 6
if end_date is empty it means its current date
How to do that?
Use DATEDIFF() to subtract the dates. Add 1 to that because it doesn't include both ends.
Use IFNULL() to replace the missing end_date with the current date.
SELECT id, value * (1 + (datediff(IFNULL(end_date, CURDATE()), start_date)) AS sum_value
FROM yourtable
I have tried looking at some similar examples like group by date range and weekdays etc but I couldnt fix it on my query.
as per my sample data screenshot, I need to only return
sum(salesamount)/sum(salescount) for week 1
and
sum(salesamount)/sum(salescount) for week 2.
Each of the week contain 5 days (in this example is wednesday - sunday).
My Attempt:
select salesstartdate, date_add(salesstartdate, interval 5 day) as gdate,
salesamount, salescount, sum(salesamount)/sum(salescount) as ATV
from testing
group by gdate;
My desired output is:
Week 1 15.34173913
Week 2 15.80365088
Calculation to get week 1 is (3507.1+3639.97+5258.77+8417.04+5994.48)/(285+273+344+478+368)
Calculation to get week 2 is the same as above except the date would now be from 8 to 12 of June.
You can do it with a subquery. In order to first group your result set properly and then execute aggregation on it:
SELECT
concat('WEEK', ' ', weekno) as `Week #`,
MIN(salesstartdate) as startDate,
MAX(salesstartdate) as endDate,
sum(salesamount)/sum(salescount) as ATV
FROM
(
SELECT
salesstartdate,
salesamount,
salescount,
WEEKOFYEAR(salesstartdate) as weekno -- get the week number of the current year
FROM
weekno
WHERE
WEEKDAY(salesstartdate) BETWEEN 2 AND 6 -- get index of week day
) as weeks
GROUP BY
weekno
I have used 2 MySQL functions here:
WEEKOFYEAR()
WEEKDAY()
Output:
WEEK 23 | 2016-06-08 | 2016-06-12 | 15.8040
WEEK 24 | 2016-06-16 | 2016-06-19 | 15.9323
and without subquery as well:
SELECT
concat('WEEK', ' ', WEEKOFYEAR(salesstartdate)) as `Week #`,
MIN(salesstartdate) as startDate,
MAX(salesstartdate) as endDate,
sum(salesamount)/sum(salescount) as ATV
FROM
weekno
WHERE
WEEKDAY(salesstartdate) BETWEEN 2 AND 6 -- get index of week day
GROUP BY
WEEKOFYEAR(salesstartdate)
You can do this way
select SUBDATE(salesstartdate, WEEKDAY(salesstartdate)) as week_range
, sum(salesamount)/sum(salescount)
from testing
where salesstartdate between SUBDATE(salesstartdate, WEEKDAY(salesstartdate))
and date_add(SUBDATE(salesstartdate, WEEKDAY(salesstartdate)), interval 5 day))
Group by week_range
Let's say I have a table that says how many items of something are valid between two dates.
Additionally, there may be multiple such periods.
For example, given a table:
itemtype | count | start | end
A | 10 | 2014-01-01 | 2014-01-10
A | 10 | 2014-01-05 | 2014-01-08
This means that there are 10 items of type A valid 2014-01-01 - 2014-01-10 and additionally, there are 10 valid 2014-01-05 - 2014-01-08.
So for example, the sum of valid items at 2014-01-06 are 20.
How can I query the table to get the sum per day? I would like a result such as
2014-01-01 10
2014-01-02 10
2014-01-03 10
2014-01-04 10
2014-01-05 20
2014-01-06 20
2014-01-07 20
2014-01-08 20
2014-01-09 10
2014-01-10 10
Can this be done with SQL? Either Oracle or MySQL would be fine
The basic syntax you are looking for is as follows:
For my example below I've defined a new table called DateTimePeriods which has a column for StartDate and EndDate both of which are DATE columns.
SELECT
SUM(NumericColumnName)
, DateTimePeriods.StartDate
, DateTimePeriods.EndDate
FROM
TableName
INNER JOIN DateTimePeriods ON TableName.dateColumnName BETWEEN DateTimePeriods.StartDate and DateTimePeriods.EndDate
GROUP BY
DateTimePeriods.StartDate
, DateTimePeriods.EndDate
Obviously the above code won't work on your database but should give you a reasonable place to start. You should look into GROUP BY and Aggregate Functions. I'm also not certain of how universal BETWEEN is for each database type, but you could do it using other comparisons such as <= and >=.
There are several ways to go about this. First, you need a list of dense dates to query. Using a row generator statement can provide that:
select date '2014-01-01' + level -1 d
from dual
connect by level <= 15;
Then for each date, select the sum of inventory:
with
sample_data as
(select 'A' itemtype, 10 item_count, date '2014-01-01' start_date, date '2014-01-10' end_date from dual union all
select 'A', 10, date '2014-01-05', date '2014-01-08' from dual),
periods as (select date '2014-01-01' + level -1 d from dual connect by level <= 15)
select
periods.d,
(select sum(item_count) from sample_data where periods.d between start_date and end_date) available
from periods
where periods.d = date '2014-01-06';
You would need to dynamically set the number of date rows to generate.
If you only needed a single row, then a query like this would work:
with
sample_data as
(select 'A' itemtype, 10 item_count, date '2014-01-01' start_date, date '2014-01-10' end_date from dual union all
select 'A', 10, date '2014-01-05', date '2014-01-08' from dual)
select sum(item_count)
from sample_data
where date '2014-01-06' between start_date and end_date;
I am having an issue with a SELECT command in MySQL. I have a database of securities exchanged daily with maturity from 1 to 1000 days (>1 mio rows). I would like to get the outstanding amount per day (and possibly per category). To give an example, suppose this is my initial dataset:
DATE VALUE MATURITY
1 10 3
1 15 2
2 10 1
3 5 1
I would like to get the following output
DATE OUTSTANDING_AMOUNT
1 25
2 35
3 15
Outstanding amount is calculated as the total of securities exchanged still 'alive'. That means, in day 2 there is a new exchange for 10 and two old exchanges (10 and 15) still outstanding as their maturity is longer than one day, for a total outstanding amount of 35 on day 2. In day 3 instead there is a new exchange for 5 and an old exchange from day 1 of 10. That is, 15 of outstanding amount.
Here's a more visual explanation:
Monday Tuesday Wednesday
10 10 10 (Day 1, Value 10, matures in 3 days)
15 15 (Day 1, 15, 2 days)
10 (Day 2, 10, 1 day)
5 (Day 3, 5, 3 days with remainder not shown)
-------------------------------------
25 35 15 (Outstanding amount on each day)
Is there a simple way to get this result?
First of all in the main subquery we find SUM of all Values for current date. Then add to them values from previous dates according their MATURITY (the second subquery).
SQLFiddle demo
select T1.Date,T1.SumValue+
IFNULL((select SUM(VALUE)
from T
where
T1.Date between
T.Date+1 and T.Date+Maturity-1 )
,0)
FROM
(
select Date,
sum(Value) as SumValue
from T
group by Date
) T1
order by DATE
I'm not sure if this is what you are looking for, perhaps if you give more detail
select
DATE
,sum(VALUE) as OUTSTANDING_AMOUNT
from
NameOfYourTable
group by
DATE
Order by
DATE
I hope this helps
Each date considers each row for inclusion in the summation of value
SELECT d.DATE, SUM(m.VALUE) AS OUTSTANDING_AMOUNT
FROM yourTable AS d JOIN yourtable AS m ON d.DATE >= m.MATURITY
GROUP BY d.DATE
ORDER BY d.DATE
A possible solution with a tally (numbers) table
SELECT date, SUM(value) outstanding_amount
FROM
(
SELECT date + maturity - n.n date, value, maturity
FROM table1 t JOIN
(
SELECT 1 n UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5
) n ON n.n <= maturity
) q
GROUP BY date
Output:
| DATE | OUTSTANDING_AMOUNT |
-----------------------------
| 1 | 25 |
| 2 | 35 |
| 3 | 15 |
Here is SQLFiddle demo
I'm trying to come up with a MySQL query to select the last record from each of the previous 7 days. If 1 of the previous 7 days is missing data, I would only get back 6 records. Here's what I have:
SELECT tracking.* FROM tracking
INNER JOIN
(SELECT MAX(lastChecked) AS maxLastChecked, id FROM tracking
WHERE lastChecked >= DATE_SUB(lastChecked, INTERVAL 7 DAY )
GROUP BY DAY(lastChecked)) as Lookup ON Lookup.id = tracking.id
WHERE tracking.propertyID = 1 ORDER BY tracking.lastChecked ASC LIMIT 7
Basically what this should do is select the final recorded entry for propertyID = 1 in the tracking table for each of the past 7 days (starting on today). However, this query is returning this to me (more than ONLY records within the last 7 days):
ID propertyID lastChecked value
2 1 2012-01-25 05:30:00 280
1 1 2012-01-26 12:34:02 268
5 1 2012-01-27 09:51:31 268
83 1 2012-02-13 00:01:07 276
Any help to fix this up would be greatly appreciated!
Try this query:
SELECT tracking.* FROM tracking
INNER JOIN
(SELECT MAX(lastChecked) AS maxLastChecked, id FROM tracking
WHERE DATEDIFF(lastChecked,NOW())<=7
GROUP BY DAY(lastChecked)) as Lookup ON Lookup.id = tracking.id
WHERE tracking.propertyID = 1 ORDER BY tracking.lastChecked ASC
I believe you should have a system date instead of "lastChecked" in this part:
DATE_SUB(lastChecked, INTERVAL 7 DAY )
Should be:
DATE_SUB(SYSDATE(), INTERVAL 7 DAY )
WHERE lastChecked >= DATE_SUB(lastChecked, INTERVAL 7 DAY )
This condition of your code is going to be true for every record as lastChecked is always greater than lastChecked -7.
So, if you need data of last 7 days replace it with
WHERE lastChecked >= DATE_SUB(SYSDATE(), INTERVAL 7 DAY )