SQL generate a table, count or function for graph - sql

Firstly I have no code to show (but for good reason). I need a pointer or direction before I try again as I have failed a few times already trying to create a recursive function and so on. Kind of given up and thought I would ask you experts as I am lost and stressed.
My Scenario is this.
Im creating a graph in PHP using Json and thats all fine. However the data I need is my issue.
I have records that have a start and an end date.
Example
ID 14
Start_Date 03/08/2021
End_Date 07/08/2021
Running a stored procedure to grab a records and count between 1 Aug to 10 Aug would display the above as a single record.
Im trying to create a line chart that would have 1 Aug to 2 Aug null then 3 Aug through 7 Aug displaying 1 and finally 8 to 10 Aug null.
1 Aug 2021 0
2 Aug 2021 0
3 Aug 2021 1
4 Aug 2021 1
5 Aug 2021 1
6 Aug 2021 1
7 Aug 2021 1
8 Aug 2021 0
9 Aug 2021 0
10 Aug 2021 0
Is this possible as I have nearly given up.
The nearest I came was using a loop to create a temporary table and inserting records was NOT pretty and certain was embarrassing. If I recreated and posted it here I would die of shame for sure.
So if anyone can point me in the right direction, offer a suggestion or anything like this would be very much appreciated.
Thank you for reading.

You need to start with a list of dates. There are many ways to generate such a list -- perhaps you have an existing table, or your database supports a function. SQL (in general) supports recursive CTEs, which is an alternative method.
Once you have the dates, you can use left join and group by to get the counts you want. Here is an example using MySQL syntax:
with recursive dates as (
select date('2021-08-01') as dte
union all
select dte + interval 1 day
from dates
where dte < '2021-08-10'
)
select d.dte, count(t.id)
from dates d left join
t
on d.dte between t.start_date and t.end_date
group by d.dte;
Here is a db<>fiddle.

Related

How to calculate Mean Time Between Failure (MTBF) using 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')

Getting the oldest datas from a table that are older than a 100 days

I've been struggling with the following problem:
EXPLAINING
I have a table called part_subhourly_data that holds production data for a part (For the purpose of the problem, no need to know what a part is).
I need to archive the any data older than a 100 days. But since there's a lot of data (they arrive each 5 or 10 minutes) and we have more than 1000 parts, I need to do it the 5 oldest days each time.
This is the schema of my table:
part_subhourly_data
id INTERGER,
part_id INTEGER,
produced_at TIMESTAMP
data HSTORE
So basically I need to get all data that is in this table, where produced_at is prior to 100 days ago and limit that to the first 5 days, per part.
Example:
Part 1 has data from 15 Aug 2016 until 12 Dec 2016
Part 2 has data from 1st Sep 2016 until 12 Dec 2016
100 days ago would be 3 Sep 2016.
For Part 1 I would take data from 15 Aug 2016 until 19 Aug 2016 (5 days).
For Part 2 I would take data from 1st Sep 2016 until 3 Sep 2016 (3 days because of the 100 days old condition).
WHAT HAVE I TRIED
Well, I'm using rails on this, but a SQL solution is welcome as well. For now, What I'm doing is to grab the oldest data with:
SELECT "part_subhourly_data"."part_id", MIN(produced_at) produced_at
FROM "part_subhourly_data"
WHERE (produced_at < (NOW() - INTERVAL '100 days'))
GROUP BY "part_subhourly_data"."part_id"
And then I loop Over each part_id and grab the data based on the MIN(produced_at). It works, but it doesn't seems ideal. I'm sure that there is some SQL magic to make it simpler, and quicker, without having to loop over each part.
Any idea?
Take all records where produced_at is prior to 100 days ago.
dense rank the records per part_id ordered by produced_at::date in ascending order.
The records with the oldest date will get 1, the records with the next oldest date will get 2 etc.
select part_id,produced_at
from (select part_id,produced_at
,dense_rank () over (partition by part_id order by produced_at::date) as dr
from part_subhourly_data
where produced_at < now() - interval '100 days'
) p
where dr <= 5
;

Grouping rows with each different row has header row SQL Server

I am trying to group some data in SQL Server. However not sure if there is a query that can do this. Below is the original data
Type Number Date Result
Car 6664441111 Feb 22 2016 IVR Detected
Car 6664441111 Feb 22 2016 Answered
Lab 5552221111 Feb 22 2016 No Answer
Lab 5552221111 Feb 22 2016 Hangup
Lab 5552221111 Feb 22 2016 Answered
I would like to know a query that can do this:
Type Number Date Result
Car 6664441111 Feb 22 2016 IVR Detected
6664441111 Feb 22 2016 Answered
Lab 5552221111 Feb 22 2016 No Answer
5552221111 Feb 22 2016 Hangup
5552221111 Feb 22 2016 Answered
I am using SQL Server. Thank you in advance
Assuimg your data is sorted already and doesn't need to be sorted to make your logic happen you could use a row_number window function:
select
CASE WHEN row_num = 1 THEN type END AS type, number, date, result
from (
select type, number, date, result, row_number() over (partition by type) AS row_num
from t
) x
If you need to order your data to appear like in your example, you need to add order by within window function.

return values within the last 365 counting from newest date ORACLE SQL

[ORACLE SQL] I'm trying to write a query that returns all the values in a single column in the last 365 days counting from the last time (or newest date; in other words) data was entered.
For example: table: EMPLOYEE_TIMESTAMPS
EMPLOYEE_ID TIMESTAMP_DATE
1 AUG 2014
1 AUG 2015
2 JAN 2016
1 FEB 2016
1 OCT 2016
the resulting data should be only the last two rows, as it should count 365 days from OCT 2016 backwards.
I tried using the following code but resulted in [ORA-00934: group function is not allowed here] because of the MAX function. Using SYSDATE does not get the job done as the last data could have been added months ago.
SELECT * FROM EMPLOYEE_TIMESTAMPS
WHERE TIMESTAMP_DATE >= MAX(TIMESTAMP_DATE) -365;
I'm fairly new to programming so I still have a hard time transmitting my ideas. Thanks for the help.
One method of doing what you want uses window functions:
SELECT *
FROM (SELECT et.*,
MAX(TIMESTAMP_DATE) OVER (PARTITION BY EMPLOYEE_ID) as MAX_TIMESTAMP_DATE
FROM EMPLOYEE_TIMESTAMPS
) et
WHERE TIMESTAMP_DATE >= MAX_TIMESTAMP_DATE - 365;
The problem with your version is the use of the aggregation function MAX(). First, there is no GROUP BY in the query. And, second, these functions are not allowed in the WHERE clause.
The MAX() in the above version is called an analytic function, because it has the OVER clause.

Get the latest date in SQL from text format

I'm trying to get the latest date from a csv file , the dates are stored in this form
NOV 14 2010
FEB 1 2012
JUN 18 2014
and my query is like
SELECT Max(date) from table
I'm getting
NOV 14 2010
any idea ?
They are likely being considered strings(varchar) not DateTimes. Try:
SELECT MAX(CAST(TABLE.date as DateTime)) FROM TABLE