Aging of Data Week Wise in Mysql - mysql

Here i have a table of task that contains task_id, created_date, completed_date, priority .
I need output that give me the records priority wise and no of week task open .
if completed_date is null than it should calculate the difference from current date.
I need mysql query that return me the record like
-----------------------------------------------------------------
|week of created | priority | Count | no of week task open |
-----------------------------------------------------------------
|40 | hi | 20 | 2(week diff of completed |
and create date)
Here is the query that give me the data when completed date is exist.
select yearweek(created_Date) AS year_week
, priority, count(*) as cnt
, yearweek(completed_date) - yearweek(created_date) as Diff
from lss_analyseTaskLogView
where diffs is not null
and diffs <> ''
and completed_date is not null
and completed_Date <> '0000-00-00'
group
by Diff
, priority;
Here is the query that give me the data when completed date is not exist.
select yearweek(created_Date) as year_week
, priority
, count(*) as cnt
, yearweek(CURRENT_DATE) - yearweek(created_date) as Diff
from lss_analyseTaskLogView
where diffs is not null
and diffs <> ''
and (completed_date is null or completed_Date = '0000-00-00 00:00')
group
by Diff
, priority;
I had combine count of both query when week difference and priority same using query
select A.year_week, A.priority, A.cnt + B.cnt As Cnt, A.Diff from
(select yearweek(created_Date) AS year_week ,priority, count(*) as cnt,
yearweek(completed_date) - yearweek(created_date) as Diff
from lss_analyseTaskLogView
where diffs is not null and diffs <> '' and completed_date is not null
and completed_Date <> '0000-00-00' group by Diff,priority) A,
(select yearweek(created_Date) as year_week,priority, count(*) as cnt,
yearweek(CURRENT_DATE) - yearweek(created_date) as Diff
from lss_analyseTaskLogView
where diffs is not null and diffs <> ''
and (completed_date is null or completed_Date = '0000-00-00 00:00')
group by Diff,priority) B
where A.Diff = B.Diff and A.priority = B.priority and A.year_week = B.year_week;
but how can i get record of first two query which are not consider in last query.
how can i get the desire set of record.
suggest me any query regarding my question .
Thanks in Advance.

Related

Need to Pick Max Date when status = N otherwise No in MYSQL

I have a table which have records like this
ID DATEADD STATUS
'A0011' '04/01/2018 11:58:31' 'C'
'A0011' '31/05/2019 10:02:36' 'N'
'B0022' '04/01/2018 11:58:31' 'N'
'B0022' '31/05/2019 10:02:36' 'N'
'B0022' '30/04/2020 19:44:36' 'C'
'C0033' '04/01/2018 11:58:31' 'N'
'C0033' '30/05/2019 06:02:36' 'C'
'C0033' '29/04/2020 05:44:36' 'C'
I'm trying to get the Max Date for each ID which have STATUS = 'N'. If I get MAX DATE and STATUS = 'C' then I don't want that record.
Output :
ID DATEADD STATUS
'A0011' '31/05/2019 10:02:36' 'N'
SCRIPT :
SELECT I.* FROM INVOICE I
INNER JOIN (
Select ID,MAX(DATEADD)DATEADD,STATUS FROM INVOICE WHERE STATUS = 'N'
GROUP BY ID,STATUS) O
ON I.ID = O.ID AND O.DATEADD = I.DATEADD
But I'm not able to get desired output.
If your mysql version support the window function, we can try to use ROW_NUMBER window function to get each ID latest DATEADD then compare the STATUS
SELECT *
FROM (
SELECT *,ROW_NUMBER() OVER(PARTITION BY ID ORDER BY DATEADD DESC) rn
FROM INVOICE
) t1
WHERE rn = 1 AND STATUS = 'N'
sqlfiddle
if your MySQL version didn't support the window function we can try to use correlated subquery
SELECT *
FROM (
SELECT *, (SELECT COUNT(*)
FROM INVOICE tt
WHERE tt.ID = t1.ID AND tt.DATEADD > t1.DATEADD) rn
FROM INVOICE t1
) t1
WHERE rn = 1 AND STATUS = 'N'
sqlfiddle
You can use NOT EXISTS:
SELECT i1.*
FROM INVOICE i1
WHERE i1.STATUS = 'N'
AND NOT EXISTS (
SELECT 1
FROM INVOICE i2
WHERE i2.ID = i1.ID
AND STR_TO_DATE(i2.DATEADD, '%d/%m/%Y %H:%i:%s') > STR_TO_DATE(i1.DATEADD, '%d/%m/%Y %H:%i:%s')
);
If the column's DATEADD data type is DATETIME or TIMESTAMP the last condition would be simpler:
...AND i2.DATEADD > i1.DATEADD
See the demo.
We can use ORDER BY and LIMIT 1 to get the row that we want without using any functions, sub-queries, CTE etc.
Thank you to D-Shih for the test schema.
If we want the maximum date with status 'N' for each ID we can use the second query.
SELECT
ID,
DATEADD,
STATUS
FROM INVOICE
ORDER BY
STATUS DESC,
DATEADD DESC
LIMIT 1;
ID | DATEADD | STATUS
:---- | :--------- | :-----
A0011 | 2019-05-31 | N
SELECT
ID,
MAX(DATEADD) AS DATEADD,
STATUS
FROM INVOICE
WHERE STATUS = 'N'
GROUP BY ID
ORDER BY ID;
ID | DATEADD | STATUS
:---- | :--------- | :-----
A0011 | 2019-05-31 | N
B0022 | 2019-05-31 | N
C0033 | 2018-01-04 | N
db<>fiddle here

Display summary data for every month in SQL for last 3 years

I have this T-SQL query that would be the total count of claims, dollar value for the date declared.
But I need to find the count and dollar value for each month beginning starting 2016 and until today / yesterday. I want to load the result set to a new table. Any thoughts or suggestions? Thanks in advance!
T-SQL query
DECLARE #AsofDATE AS DATE
DECLARE #AsofDateINT AS INT
SET #AsofDATE = '1/1/2018'
SET #AsofDateINT = 20180101
SELECT
COUNT(S.ClaimNum) Count_of_Claims,
SUM(ReserveIndemnityAmount) AS RD_REserve,
#AsofDATE AS AsofDate
-- INTO #tempRD
FROM
(SELECT
f.*,
ROW_NUMBER() OVER (PARTITION BY ClaimNum ORDER BY f.ModifiedDate DESC) AS Row_order_desc
FROM
[dbo].[Snapshot] f
WHERE
CAST(f.ModifiedDate AS DATE) <= #AsofDATE) S
LEFT OUTER JOIN
(SELECT
ClaimKey, SUM( t.LossRsvAmt) AS ReserveIndemnityAmount
FROM
Stg.Claim_Transaction t
WHERE
TransactionDate < #AsofDateINT
GROUP BY
ClaimKey) T ON t.ClaimKey = s.ClaimID
WHERE
S.Row_order_desc = 1
AND S.DerivedClaimStatus NOT IN ('Closed', 'Cancelled', 'Abandoned', 'Record only', 'Opened in error' )
AND s.specialty = 'RD'
Current result:
Count_of_Claims RD_REserve AsofDate
-------------------------------------------------
15317 112192.15 2018-01-01
Expected result:
Count_of_Claims RD_REserve AsofDate
-------------------------------------------------
15317 112192.15 2017-01-12
15567 111592.15 2017-01-11
15356 15492.15 2017-01-10
Your AsofDate is hardcoded to return. Why not replace that with ModifiedDate?
so something like
select
count(s.claimnum) countofclaims
,sum(amount) amount
,cast(eomonth(modifieddate) as date) [asofdate]
from your query...
group by
cast(eomonth(modifieddate) as date)

How to get column value from next record

I have a following result set:
POST | DATE
--------------------------------------
Senior Software Engg. | 2018-04-18
Software Engg. | 2017-04-18
Assoc. Software Engg. | 2016-04-18
SQL query:
SELECT DISTINCT designation_id as id, d.title as POST, DATE(dt_datetime) as DATE
FROM users_history_check u
INNER JOIN
designations d
ON d.id = u.designation_id
WHERE u.id = $userID
ORDER BY DATE DESC
I want to fetch next record and perform date difference calculation in months, and display records.
Expected Output :
POST | Start DATE | End DATE | MONTHS
---------------------------------------------------------------
Senior Software Engg. | 2018-04-18 | - |
Software Engg. | 2017-04-18 | 2018-04-18 | 12
Assoc. Software Engg. | 2016-04-18 | 2017-04-18 | 12
Something like :
SELECT DISTINCT designation_id as id, d.title as POST, DATE(dt_datetime) as Start DATE, NEXT_RECORD(DATE(dt_datetime)) as End DATE, DATEDIFF(Start DATE, End DATE) as MONTHS....
Any help is very much appreciated. Thanks.
SELECT `POST`,
`DATE`,
IFNULL(END_DATE,'') AS END_DATE,
IFNULL(MONTH,'') AS MONTH
FROM
(SELECT `POST`,
`DATE`,
#prev AS END_DATE,
TIMESTAMPDIFF(month,DATE,#prev) AS MONTH,
#prev := T.DATE AS VarDate
FROM Table1 T,
(SELECT #prev:=null)R
) T1
OUTPUT
POST DATE END_DATE MONTH
Senior Software Engg. 2018-04-18
Software Engg. 2017-04-18 2018-04-18 12
Assoc. Software Engg. 2016-04-18 2017-04-18 12
Demo Link
http://sqlfiddle.com/#!9/33260/15
EXPLANATION:
In Sub query, I am saving the Date value in #prev variable and in each row using that variable to calculate the END_DATE before assigning the current date value from Column Date.
Then using the sub query to present the data in a proper way.
You can get the previous date using variables:
SELECT id, post, date,
(CASE WHEN (#tmp_prevd := #prevd) = NULL THEN NULL -- never happens
WHEN (#prevd := date) = NULL THEN NULL -- never happens
ELSE #tmp_prevd
END) as prev_date
FROM (SELECT DISTINCT designation_id as id, d.title as POST, DATE(dt_datetime) as DATE
FROM users_history_check u INNER JOIN
designations d
ON d.id = u.designation_id
WHERE u.id = $userID
ORDER BY DATE DESC
) ud CROSS JOIN
(SELECT #prevd := NULL) params;
This is tricky, because all references to a variable need to be in the same expression. That is why this uses CASE in a rather arcane way.
In MySQL 8.0 and basically all other databases, you could use LEAD() instead.
Try This....
SELECT T1.POST,T1.DATE ,T2.DATE,DATEDIFF(MONTH,T1.DATE,T2.DATE)
FROM(
SELECT ROW_NUMBER()OVER(ORDER BY DATE DESC) AS SlNo,*
FROM Mytable)T1
LEFT JOIN (SELECT ROW_NUMBER()OVER(ORDER BY DATE DESC)+1 AS SlNo,*
FROM Mytable)T2
ON(T1.SlNo = T2.SlNo )
I suggest using self-join like this
select d1.post,
d1.d `start DATE`,
min(d2.d) `end DATE`,
timestampdiff(month, d1.d, min(d2.d)) `MONTHS`
from data d1
left join data d2 on d1.d < d2.d
group by d1.post, d1.d
dbfiddle demo
The data table is the result of your SQL. It can be added using WITH or you may use subquery as well.
SELECT * ,Datediff(Month,[Date],endate)
FROM
(
SELECT *,Lead( [Date], 1, Null) OVER (
ORDER BY [Date]) AS Endate --INTO SourceTable
FROM
(
SELECT 'Senior Software Engg.' POST , '2018-04-18' DATE UNION ALL
SELECT 'Software Engg.' POST , '2017-04-18' DATE UNION ALL
SELECT 'Assoc. Software Engg.' POST , '2016-04-18' DATE
)A
)B
ORDER BY [Date] desc

Finding local maximum between zero-values using SQL

I have a table with minute-by-minute data from an IOT device. Every minute there is a new row with a timestamp and a value that represents a metric. The metric starts at 0 and increments for a while before it resets and starts over.
When I plot it, it looks like the picture. I want to find the local maximum value of each run, as the blue circles indicate.
Is it possible to find and group the consecutive rows where the metric is > 0 and then find the maximum of each group?
Update
Table structure:
+-------------+------------------+
| Field | Type |
+-------------+------------------+
| id | int(10) unsigned |
| timestamp | timestamp |
| metric_name | varchar(32) |
| value | int(10) |
+-------------+------------------+
This is based on the following assumptions:
Id is a perfectly sequential integer (with no gaps)
You want to get the value logged directly before the 0 value
Code:
SELECT *
FROM metrics m1
WHERE m.id IN (
SELECT m2.id - 1
FROM metrics m2
WHERE m1.value = 0)
I join everything that isnt zero before a timestamp where it is zero, then I find the ones with no values inbetween that 0 and the last one..
SELECT
value,
timestamp
FROM
metrics
LEFT JOIN metrics zeros
on metrics.time < zeros.time
and zeros.value = 0
LEFT JOIN metrics betweenZero
on metrics.time < betweenZero.time
and betweenZero.time < zeros.time
INNER JOIN metrics noBetweens
on table.id = noBetweens.id
and betweenZero.id IS NULL
If you need it for a paritulcar metric_name, WHERE metric_name = the_metric_nameon the end.
This should give you the max value per group along with start time and end time of each window with only 1 pass over the data.
select metric_name, max(value) value, max(start_group) start_time, max(end_group) end_time from(
select metric_name, value,
case when #prev_ts is not null then #prev_ts end prev_ts,
case when value = 0 then #ts := timestamp end as start_group,
#ts as grouping,
#prev_ts := timestamp end_group
from metric join (select #prev_ts := null as p) prev
order by timestamp
) q
group by metric_name, grouping;
This will create a sample data set of 1000 rows, that resets every minute.
insert into metric(timestamp, metric_name, value)
select now() - interval rn second, 'pressure', v
from(
select #rn := #rn + 1 rn, mod(1000 - #rn,60) * pow(1000 - mod(#rn,121),1) v
from table_with_at_least_1000_rows
join (select #rn := 0) rn
limit 1000
) q
;
Try this:
SELECT
T.min_id
,T.max_id
,MAX(M.value) as local_max
FROM
metrics M
JOIN (
SELECT
id as min_id
,(
SELECT MIN(id) FROM Metrics MI
WHERE
MI.id > MO.id
AND MI.value = 0) as max_id
FROM Metrics MO
WHERE
value = 0
)T ON M.id BETWEEN T.min_id AND T.max_id
GROUP BY
T.min_id, T.max_id
My solution doesn't care about gaps but I am assuming that the sequence of ids is monotonic, that is they increase along the series by time. (You could probably substitute id for timestamp in the query even.) I had made a few minor syntax-type errors that I have since corrected since my first attempt and I have tested it with a simple Fiddle. I think it works.
select t0.*
from
T t0 inner join
(
select max_z, max(id) as max_id, max(value) as local_max
from
(
select
id, value,
(
select max(t2.id) as max_id from T t2
where t2.id < t.id and t2.value = 0
) as max_z
from T t
where t.value <> 0
) p /* partitions */
group by p.max_z
) x /* extrema */
on t0.id between max_z and max_id and t0.value = x.local_max
Btw it returns all the rows when there's a tie for the local maximum.
http://sqlfiddle.com/#!9/de832/2

Union All does not return the same number of rows

I have a sql query that uses union all. When i run the following query only one row with NULL value is returned (the value is null because there is no data for that time period). The expectation was that 2 rows with null would be returned. What gives?
SELECT
SUM(val) AS GA
FROM
mytable
WHERE region = 'someRegion'
AND ACTIVITY_MTH BETWEEN '2014-04-01' AND '2014-04-30'
UNION
ALL
SELECT
quota
FROM
budgetTable
WHERE sales_id = 'someRegion'
AND start_date = '2014-04-01'
AND metric_id = 1