How to calculate Mean Time Between Failure (MTBF) using SQL - sql

Given Issue Raised day and count, how can we come up with the calculation of Datediff, and the output table with MTBF for each month? Thanks a lot.
Raw data
Issue Raised | Count | Datediff
1/12/22 1 12
2/23/22 1 42
4/1/22 2 37
4/7/22 1 6
Output table
Month | MTBF
Jan 12/1=12
Feb 42/1=42
Mar
Apr (37+6)/(2+1)=14.33

As mentioned you could use a group by function to aggregate by month, year and then do your calculations. Here is something that might work for you, however I am uncertain of your DBMS.
SELECT
FORMAT(ISSUERAISED, 'MM-yyyy') AS Month_Year
,SUM("Count") AS "Count"
,SUM("DateDiff") AS "DATEDIFF"
, SUM(CAST("DateDiff" AS DECIMAL(7,4))) / SUM(CAST("Count" AS DECIMAL(7,4))) AS MTBF
FROM YOURTABLE
GROUP BY FORMAT(ISSUERAISED, 'MM-yyyy')

Related

Find and sort all the data(dates) after a certain date by month/day and not year in SQLite

I wanna order the data in an sqlite3 database by date. (Day and Month to be precise)
I have a table,
the data in the table are in the format YYYY-MM-DD
2003-02-20, 2005-07-16, 2008-11-18, 1998-01-02, 1996-08-27
Here, I wanna find all the data after a certain date(Current date- 'now') and in order.
The data is birthdays, so the order should be just based off of Month and Day and shouldn't care about the year.
For example, the data here is
Feb 20, Jul 16, Nov 18, Jan 1, Aug 27
current day= July 28
I want the output to look like
Aug 27, Nov 18, Jan 1, Feb 20, Jul 16
I've looked through many examples and documentations and tried some methods
SELECT * FROM table WHERE birthdays>date('now')
*birthdays are the column where dates are stored*
This gives all the data after ('now') as an output, but it orders it by year as well. Hence, the output will be none since none of the years are greater than current year. I wanna take the year out of the equation and just order it by Month and Day.
How can I do it?
You don't need a WHERE clause because all rows of the table should be returned.
What you want is a proper ORDER BY clause:
SELECT *
FROM tablename
ORDER BY strftime('%m-%d', birthdays) > strftime('%m-%d', 'now') DESC,
strftime('%m-%d', birthdays);
See the demo.
According to the sample data and the expected output you posted, you want to find all birthdays that will occur this year after the date of today. You may use the strftime function to extract month and day as the following:
Select user_id, DOB
From your_table
Where strftime('%m-%d',DOB) > strftime('%m-%d',date())
Order By strftime('%m-%d',DOB)
See a demo from db-fiddle.
you can select the dates, by taking he day of birth, adding the current year ( or the next one if it is smalerer tan the current date)and then selecting the dates that are bigger than the current date limiting 10
SELECT user_id, DOB
FROM your_table
ORDER BY
CASE WHEN date(strftime('%Y', date('now')) || strftime('-%m-%d', DOB)) > DATE() then date(strftime('%Y', date('now')) || strftime('-%m-%d', DOB))
ELSE date(strftime('%Y', date('now','+1 years')) || strftime('-%m-%d', DOB)) END
LIMIT 10;
user_id DOB
5 1996-08-27
10 1996-08-27
15 1996-09-27
13 2008-10-18
3 2008-11-18
8 2008-11-18
4 1998-01-02
9 1998-01-02
14 1998-01-02
1 2003-01-31
db<>fiddle here

How to create a query to get invoices between dates (help needed)

I need to create a query in SQL to get some invoices depending on the current date. I'm an intern in the company, so I only need to create the logic, not necessarily the query. Can anyone help me to translate this conditions into SQL (Snowflake)?
If Current Date (today's date) is between day 14 and 27 of the month >>> Get
invoices from day 14 of the current month
If Current Date (today's date) is between day 28 and 31 of the month >>> Get
invoices from day 28 of the current month
If Current Date (today's date) is between day 1 and 13 of the month >>> Get invoices
from day 28 of the last month
Thanks in advance!
I think your simplest, clearest option is a case statement.
You can put this into your select and work with it from there, or put it directly into a where clause. whatever's more appropriate for your query.
WHERE invoice_date::DATE = (CASE WHEN DAY(current_date) between 14 and 27 then DATE_FROM_PARTS(YEAR(current_date), MONTH(current_date), 14)
WHEN DAY(current_date) between 28 and 31 then DATE_FROM_PARTS(YEAR(current_date), MONTH(current_date), 28)
WHEN DAY(current_date) between 1 and 13 then DATEADD('month', -1, DATE_FROM_PARTS(YEAR(current_date), MONTH(current_date), 28))
END)
select
current_date()+1 your_date
,dateadd(day,27-(sign(FLOOR(day(your_date)/14,0))*14)
,dateadd(month,sign(FLOOR(day(your_date)/14,0))-1
,date_trunc(month,your_date))) your_result
Revised solution.
Removing inequalities and reducing the problem down to multiples of 14 with month adjustments instead of multiple case statements (expensive to run at scale).

BigQuery : is it possible to execute another query inside an UDF?

I have a table that records a row for each unique user per day with some aggregated stats for that user on that day, and I need to produce a report that tells me for each day, the no. of unique users in the last 30 days including that day.
eg.
for Aug 31st, it'll count the unique users from Aug 2nd to Aug 31st
for Aug 30th, it'll count the unique users from Aug 1st to Aug 30th
and so on...
I've looked at some related questions but they aren't quite what I need - if a user logs in on multiple days in the last 30 days he should be counted only once, so I can't just sum the DAU count for the last 30 days.
Bigquery SQL for sliding window aggregate
BigQuery SQL for 28-day sliding window aggregate (without writing 28 lines of SQL)
So far, my ideas are to either:
write a simple script that'll execute a separate BigQuery for each of the relevant days
write a BigQuery UDF that'll execute basically the same query for each day selected from another query
but I've not found any examples on how to execute another BigQuery query inside an UDF, or if it's possible at all.
I need to produce a report that tells me for each day, the no. of
unique users in the last 30 days including that day.
Below should do this
SELECT
calendar_day,
EXACT_COUNT_DISTINCT(userID) AS unique_users
FROM (
SELECT calendar_day, userID
FROM YourTable
CROSS JOIN (
SELECT DATE(DATE_ADD('2016-08-08', pos - 1, "DAY")) AS calendar_day
FROM (
SELECT ROW_NUMBER() OVER() AS pos, *
FROM (FLATTEN((
SELECT SPLIT(RPAD('', 1 + DATEDIFF('2016-09-08', '2016-08-08'), '.'),'') AS h
FROM (SELECT NULL)),h
)))
) AS calendar
WHERE DATEDIFF(calendar_day, dt) BETWEEN 0 AND 29
)
GROUP BY calendar_day
ORDER BY calendar_day DESC
It assumes YourTable has userID and dt fields (like below for example)
dt userID
2016-09-08 1
2016-09-08 2
...
And you can control:
- reporting dates range by changing respectively 2016-08-08 and 2016-09-08
- aggregation size by changing 29 in BETWEEN 0 AND 29

Dividing by number of days not referencing correct month/number of days

I have a table that users enter a daily population. How many people in a particular facility that day. The table looks similar to this:
select * from stat_summary where MONTH(report_date) = 9
results:
stat_summary_id | report_date | facility | adp
----------------------------------------------------
29 |2015-09-01 | YORK | 1855
30 |2015-09-02 | YORK | 1750
31 |2015-09-04 | YORK | 1655
32 |2015-09-04 | YORK | 1699
What I want to do is calculate the average daily population grouped by month. I want to take the MAX(report_date) in case a corrected value has to be re-entered. My query looks like:
SELECT
MONTH(t.report_date) as 'report_month',
SUM(ss1.adp)/DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,MONTH(t.report_date)),0))),
DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,MONTH(t.report_date)),0)))
FROM
stat_summary ss1
INNER JOIN
(SELECT MAX(stat_summary_id) as 'stat_summary_id', report_date
FROM stat_summary
GROUP BY report_date
) t ON t.stat_summary_id = ss1.stat_summary_id
WHERE
ss1.facility_id = 'YORK'
AND MONTH(t.report_date) = 9
GROUP BY
MONTH(t.report_date)
ORDER BY
MONTH(t.report_date)
I've referenced this thread:
Dividing a value by number of days in a month in a date field in SQL table
And I was able to see how to dynamically divide by the number of days in the month, but it looks like it is dividing by the current month (October) which has 31 days, when I need the query to divide by the referenced month of September which has 30 days.
Currently my results look like:
The adp value should be 176.8 since there are 30 days in September, not 31.
So quick check it looks like that formula returns 31 for all months. The proper formula can be found here: How to determine the number of days in a month in SQL Server?
datediff(day, dateadd(day, 1-day(#date), #date),
dateadd(month, 1, dateadd(day, 1-day(#date), #date)))
More precisely use:
datediff(day, dateadd(day, 1-day(MIN(t.report_date)), MIN(t.report_date)),
dateadd(month, 1, dateadd(day, 1-day(MIN(t.report_date)), MIN(t.report_date))))
EDIT: Note the original formula was in fact correct, the problem was that you were passing in a month instead of a day. Months are numbers from 1-12, so all of your dates were in January.
I should use
day(DateAdd(day, DateAdd(month, MONTH(t.report_date), DateAdd(Year, YEAR(t.report_date)-1900, 0)), -1)) as monthDays
Also sounds to me that to obtain average, it is wrong to divide by that number, it is only correct if the number of records match the number of days in the month, in other case, just the count is enough
SUM(ss1.adp)/count(ss1.adp) as average

Oracle correctly getting the month difference

Hi Ive been having an issue with getting the correct difference in a date from the current month not including the day.
ie if the month when the query is run is march 2013
then the following should be the result
EXECUTION_DATE, EXEC_DIFF
01-FEB-13, 1
31-JAN-13, 2
30-JAN-13, 2
however using the below sql statement im getting
EXECUTION_DATE, EXEC_DIFF
01-FEB-13, 1
31-JAN-13, 2
30-JAN-13, 1
select EXECUTION_DATE,
floor(MONTHS_BETWEEN (trunc(sysdate,'MM')-1, EXECUTION_DATE))+1 "EXEC_DIFF"
from V_CERT_LIST
WHERE EXECUTION_DATE < TO_DATE('02/02/2013','DD/MM/YYYY')
ORDER BY EXECUTION_DATE DESC
Please can someone put me right ive been bashing my head with this for some time now
thanks
select EXECUTION_DATE,
MONTHS_BETWEEN (trunc(sysdate,'MM'), trunc(EXECUTION_DATE,'MM')) "EXEC_DIFF"
from V_CERT_LIST
WHERE EXECUTION_DATE < TO_DATE('02/02/2013','DD/MM/YYYY')
ORDER BY EXECUTION_DATE DESC
Not looking for scores but cannot understand what is the problem with months_between? In my understanding it does not matter when in month execution takes place - Jan-31 or Jan 30... The difference is still 2 months between Jan and Mar as in your example. I can add more days in month in the query but mo_betw. will still be the same...:
SELECT to_char(exec_date, 'DD-MON-YYYY') exec_date, MONTHS_BETWEEN(run_date, exec_date) months_btwn
FROM
(
SELECT to_date('01/03/2013', 'DD/MM/YYYY') run_date
, Add_Months(Trunc(sysdate,'YEAR'),Level-1) exec_date -- first day of each month
FROM dual
CONNECT BY LEVEL <= 3
)
/
EXEC_DATE MONTHS_BTWN
------------------------
01-JAN-2013 2
01-FEB-2013 1
01-MAR-2013 0
Months_Between has complex logic that takes the day of the month into account.
Perhaps what you want is this:
select EXECUTION_DATE,
((year(sysdate)*12+month(sysdate)) - (year(execution_date)*12 + month(execution_date))
) as Exec_Diff
from V_CERT_LIST
WHERE EXECUTION_DATE < TO_DATE('02/02/2013','DD/MM/YYYY')
ORDER BY EXECUTION_DATE DESC
This converts the year/month combination into the number of months since 0 time and then subtracts the results.