How to build logic to find the history of Red and Amber records with below example - sql

with archer_summary_base as (select * from kri.archer_kri_latest_summary
where segment='All Segments' and Level_I_Risk!='' and metric_identifier in ('Mandatory') and (metric_results_status='Amber' or metric_results_status='Red' or metric_results_status is null) and
(month='January' or month='February' or month='March' or month='December' or month='November' or month='April' or month is null) AND (year=2021 or year=2020 or year is null)
and status='Active' and originated_source ='Archer'),
--select * from archer_summary_base
archer_summary_main as (select * from kri.archer_kri_latest_summary where metric_id in (select metric_id from archer_summary_base)
and (month='January' or month='February' or month='March' or month='December' or month='November' or month='April' or month is null)
AND (year=2021 or year=2020 or year is null) and segment='All Segments' and Level_I_Risk !='' and originated_source ='Archer' and
metric_identifier in ('Mandatory')),
breach_kri_report AS (select metric_id,
trim(Level_I_Risk) as Level_I_Risk,
trim(Metric_Name) as Metric_Name,
(case when format in ('Percentage') then concat(regexp_replace(regexp_replace(Green_threshold_min,'\\.0+$',''),'(\\d+\\.\\d+?)0+$','$1'),'%','-',regexp_replace(regexp_replace(Green_threshold_max,'\\.0+$',''),'(\\d+\\.\\d+?)0+$','$1'),'%')
when format in ('Monetary Amount') then concat('$',format_number(cast(Green_threshold_min as bigint),0),' -','$',format_number(cast(Green_threshold_max as bigint),0))
when format in ('Number') then concat(cast(Green_threshold_min as bigint),'-',cast(Green_threshold_max as bigint))
end) as Green_Threshold,
trim(PATH_TO_GREEN_INDICATOR) as P2G_Indicator,
concat(substring(Month,1,3), '-', substring(year,3,4)) as Month_Name,
(case when format in ('Percentage') then concat(cast(metric_value as bigint),'%')
when format in ('Monetary Amount') then concat('$',(format_number(cast(metric_value as bigint),0)))
when format in ('Number') then format_number(cast(metric_value as bigint),0) end) as DerivedValue_Avg
from archer_summary_main group by metric_id,Level_I_Risk,Metric_Name,Green_threshold_min,Green_threshold_max,PATH_TO_GREEN_INDICATOR,month,year,format,metric_value),
--Select * from breach_kri_report,
exsummary as (SELECT b.Level_I_Risk,
b.Metric_Name,
b.Green_Threshold,
b.P2G_Indicator,
case when Month_Name='Nov-20' then DerivedValue_Avg end as Nov_20,
case when Month_Name='Dec-20' then DerivedValue_Avg end as Dec_20,
case when Month_Name='Jan-21' then DerivedValue_Avg end as Jan_21,
case when Month_Name='Feb-21' then DerivedValue_Avg end as Feb_21,
case when Month_Name='Mar-21' then DerivedValue_Avg end as Mar_21,
case when Month_Name='Apr-21' then DerivedValue_Avg end as Apr_21
FROM breach_kri_report b)
select
t.Level_I_Risk,
t.Metric_Name,
t.Green_Threshold,
t.P2G_Indicator,
collect_list(Nov_20)[0] as Nov_20,
collect_list(Dec_20)[0] as Dec_20,
collect_list(Jan_21)[0] as Jan_21,
collect_list(Feb_21)[0] as Feb_21,
collect_list(Mar_21)[0] as Mar_21,
collect_list(Apr_21)[0] as Apr_21
from exsummary t
group by t.Level_I_Risk, t.Metric_Name, t.Green_Threshold, t.P2G_Indicator
Below results i am getting shown in screen shot
the 'Green' which are circled should not come when I run the query because I want to get history for Red and amber. I am ok to get the green records as part of the history but not in the beginning or in the latest months
Below is what I am trying to achieve

Here is an outline to a possible query:
Issue a subquery using a window function, partition by year and month, pick the lowest pk_key by sorting by year, month and pk_key ascending and select the first result for each partition.
Then use the results in combination with a where clause and a second constraint:
... where not(pk_key in (first_query.pk_key) and metric_results_status = 'GREEN')
Sorry, but I can't provide anything more specific, since the details you gave are not very clear on as to what your database structure in actuality looks like.
May God have mercy upon your soul!

Related

Calculate time span between two specific statuses on the database for each ID

I have a table on the database that contains statuses updated on each vehicle I have, I want to calculate how many days each vehicle spends time between two specific statuses 'Maintenance' and 'Read'.
My table looks something like this
and I want to result to be like this, only show the number of days a vehicle spends in maintenance before becoming ready on a specific day
The code I written looks like this
drop table if exists #temps1
select
VehicleId,
json_value(VehiclesHistoryStatusID.text,'$.en') as VehiclesHistoryStatus,
VehiclesHistory.CreationTime,
datediff(day, VehiclesHistory.CreationTime ,
lead(VehiclesHistory.CreationTime ) over (order by VehiclesHistory.CreationTime ) ) as days,
lag(json_value(VehiclesHistoryStatusID.text,'$.en')) over (order by VehiclesHistory.CreationTime) as PrevStatus,
case
when (lag(json_value(VehiclesHistoryStatusID.text,'$.en')) over (order by VehiclesHistory.CreationTime) <> json_value(VehiclesHistoryStatusID.text,'$.en')) THEN datediff(day, VehiclesHistory.CreationTime , (lag(VehiclesHistory.CreationTime ) over (order by VehiclesHistory.CreationTime ))) else 0 end as testing
into #temps1
from fleet.VehicleHistory VehiclesHistory
left join Fleet.Lookups as VehiclesHistoryStatusID on VehiclesHistoryStatusID.Id = VehiclesHistory.StatusId
where (year(VehiclesHistory.CreationTime) > 2021 and (VehiclesHistory.StatusId = 140 Or VehiclesHistory.StatusId = 144) )
group by VehiclesHistory.VehicleId ,VehiclesHistory.CreationTime , VehiclesHistoryStatusID.text
order by VehicleId desc
drop table if exists #temps2
select * into #temps2 from #temps1 where testing <> 0
select * from #temps2
Try this
SELECT innerQ.VehichleID,innerQ.CreationDate,innerQ.Status
,SUM(DATEDIFF(DAY,innerQ.PrevMaintenance,innerQ.CreationDate)) AS DayDuration
FROM
(
SELECT t1.VehichleID,t1.CreationDate,t1.Status,
(SELECT top(1) t2.CreationDate FROM dbo.Test t2
WHERE t1.VehichleID=t2.VehichleID
AND t2.CreationDate<t1.CreationDate
AND t2.Status='Maintenance'
ORDER BY t2.CreationDate Desc) AS PrevMaintenance
FROM
dbo.Test t1 WHERE t1.Status='Ready'
) innerQ
WHERE innerQ.PrevMaintenance IS NOT NULL
GROUP BY innerQ.VehichleID,innerQ.CreationDate,innerQ.Status
In this query first we are finding the most recent 'maintenance' date before each 'ready' date in the inner most query (if exists). Then calculate the time span with DATEDIFF and sum all this spans for each vehicle.

How to use CASE WHEN in group by

I want to use group by for the table NRW_MONTH_DATA.
SELECT [OBJECT_ID]
,[YEAR_MONTH]
,[SELLING_AMOUNT]
,[DEFAULT_SELLING_DATA]
,[LOCK_SELLING_AMOUNT]
,[RGCB]
,[ICKZ]
,[YCKZ]
FROM [dbo].[NRW_MONTH_DATA]
IF LOCK_SELLING_AMOUNT is 0 then group by OBJECT_ID and calculate the sum of [RGCB],[ICKZ] and [YCKZ]
SELECT #SELLING_AMOUNT=(ISNULL(SUM(YCKZ),0)+ISNULL(SUM(RGCB),0)+ ISNULL(SUM(ICKZ),0))
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID
AND YEAR_MONTH >=#SELLING_CENSUS_START_YM
AND YEAR_MONTH <=#SELLING_CENSUS_END_YM
GROUP BY OBJECT_ID
Now I want to add a condition that if LOCK_SELLING_AMOUNT is 1 , I need to
SELECT #SELLING_AMOUNT=ISNULL(SUM(DEFAULT_SELLING_DATA),0)
ELSE use original result to calculate the sum of the 3 columns.
I use CASE WHEN but is seems that I could not use it in group by
SELECT #SELLING_AMOUNT=
CASE LOCK_SELLING_AMOUNT WHEN 1 THEN SELLING_AMOUNT
ELSE (ISNULL(SUM(YCKZ),0)+ISNULL(SUM(RGCB),0)+ ISNULL(SUM(ICKZ),0))
END
The error is like
The column'dbo.NRW_MONTH_DATA.LOCK_SELLING_AMOUNT' in the select list is invalid because the column is not included in the aggregate function or GROUP BY clause.
Thank you in advance.
I need the group by to calculate the sum of them. Each row has an object_id and a LOCK_SELLING_AMOUNT and other columns for one month, I want to use group to calculate the sum during month span.
It works well when I do not consider the LOCK_SELLING_AMOUNT
First, you don't want GROUP BY. So just use:
SELECT #SELLING_WATER = (COALESCE(SUM(YCKZ), 0) + COALESCE(SUM(RGCB), 0)+ COALESCE(SUM(ICKZ), 0))
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID AND
YEAR_MONTH >= #SELLING_CENSUS_START_YM
YEAR_MONTH <= #SELLING_CENSUS_END_YM;
Now, the problem is that a column can change values on different rows. So, what row does LOCK_SELLING_AMOUNT come from? We could assume it is the same on all rows. Or perhaps you want an aggregation function:
SELECT #SELLING_WATER = (CASE WHEN MAX(LOCK_SELLING_AMOUNT) = 1
THEN MAX(CASE WHEN LOCK_SELLING_AMOUNT = 1 THEN SELLING_AMOUNT END)
ELSE (COALESCE(SUM(YCKZ), 0) + COALESCE(SUM(RGCB), 0)+ COALESCE(SUM(ICKZ), 0))
END)
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID AND
YEAR_MONTH >= #SELLING_CENSUS_START_YM
YEAR_MONTH <= #SELLING_CENSUS_END_YM;

SQL Case Statements with Multiple Max Conditions

I currently am working with two conditions that I would like to combine into one, but ran into some trouble. I have a dataset that includes quantity and date. I have created a date flag in the form of a case statement that flags whether it is the last day of the week, and gives it a "Y" or "N". The end result that I need is what that last DATE of the week.
My end result/goal is Column D
Here is my current source code:
select
pos.quantity_on_hand,
d.cal_date,
case
when date_key in( Select max(date_key) from edw.D_dates group by fiscal_year_nbr, fiscal_week_nbr)
then 'Y'
else 'N'
end Week_end_flag
from
edw.f_pos_daily pos,
edw.d_dates d,
where
pos.pos_date_key = d.date_key
I then create another custom column in PowerBI Desktop that looks like this:
This is what I used for my column calculation:
Last Inventory Date = RETURN(CALCULATE(MAXX(Inventory, Inventory[Cal_date]), filter ('D_Dates', 'D_Dates'[Week_end_flag]="Y")).
I tried to combine them into one, with something like this, but have failed:
case
when date_key in( Select max(date_key) from edw.D_dates group by fiscal_year_nbr, fiscal_week_nbr)
then MAX (cal_date) from edw.D_Dates where cal_date< current_date AS 'yyyy-mm-dd'
else 'N'
end Week_End_flag
Use the select command inside the then clause
change this line:
then MAX (cal_date) from edw.D_Dates where cal_date< current_date AS 'yyyy-mm-dd'
to:
then (SELECT MAX (cal_date) from edw.D_Dates where cal_date< current_date AS 'yyyy-mm-dd')
complete code:
select
pos.quantity_on_hand,
d.cal_date,
case
when date_key in( Select max(date_key) from edw.D_dates group by fiscal_year_nbr, fiscal_week_nbr)
then (SELECT MAX (cal_date) from edw.D_Dates where cal_date< current_date AS 'yyyy-mm-dd')
else 'N'
end Week_end_flag
from
edw.f_pos_daily pos,
edw.d_dates d,
where
pos.pos_date_key = d.date_key

COUNT from DISTINCT values in multiple columns

If this has been asked before, I apologize, I wasn't able to find a question/solution like it before breaking down and posting. I have the below query (using Oracle SQL) that works fine in a sense, but not fully what I'm looking for.
SELECT
order_date,
p_category,
CASE
WHEN ( issue_grp = 1 ) THEN '1'
ELSE '2/3 '
END AS issue_group,
srt AS srt_level,
COUNT(*) AS total_orders
FROM
database.t_con
WHERE
order_date IN (
'&Enter_Date_YYYYMM'
)
GROUP BY
p_category,
CASE
WHEN ( issue_grp = 1 ) THEN '1'
ELSE '2/3 '
END,
srt,
order_date
ORDER BY
p_category,
issue_group,
srt_level,
order_date
Current Return (12 rows):
Needed Return (8 rows without the tan rows being shown):
Here is the logic of total_order column that I'm expecting:
count of order_date where (srt_level = 80 + 100 + Late) ... 'Late' counts needed to be added to the total, just not be displayed
I'm eventually adding a filled_orders column that will go before the total_orders column, but I'm just not there yet.
Sorry I wasn't as descriptive earlier. Thanks again!
You don't appear to need a subquery; if you want the count for each combination of values then group by those, and aggregate at that level; something like:
SELECT
t1.order_date,
t1.p_category,
CASE
WHEN ( t1.issue_grp = 1 ) THEN '1'
ELSE '2/3 '
END AS issue_group,
t1.srt AS srt_level,
COUNT(*) AS total_orders
FROM
database.t_con t1
WHERE
t1.order_date = TO_DATE ( '&Enter_Date_YYYYMM', 'YYYYMM' )
GROUP BY
t1.p_category,
CASE
WHEN ( t1.issue_grp = 1 ) THEN '1'
ELSE '2/3 '
END,
t1.srt,
t1.order_date
ORDER BY
p_category,
issue_group,
srt_level,
order_date;
You shouldn't be relying on implicit conversion and NLS settings for your date argument (assuming order_date is actually a date column, not a string), so I've used an explicit TO_DATE() call, using the format suggested by your substitution variable name and prompt.
However, that will give you the first day of the supplied month, since a day number isn't being supplied. It's more likely that you either want to prompt for a full date, or (possibly) just the year/month but want to include all days in that month - which IN() will not do, if that was your intention. It also implies that stored dates all have their time portions set to midnight, as that is all it will match on. If those values have non-midnight times then you need a range to pick those up too.
I got it working to the extent of what my question was. Just needed to nest each column where counts/calculations were happening.
SELECT
order_date,
p_category,
issue_group,
srt_level,
order_count,
SUM(order_count) OVER(
PARTITION BY order_date, issue_group, p_category
) AS total_orders
FROM
(
SELECT
order_date,
p_category,
CASE
WHEN ( issue_grp = 1 ) THEN '1'
ELSE '2/3 '
END AS issue_group,
srt AS srt_level,
COUNT(*) AS order_count
FROM
database.t_con
WHERE
order_date IN (
'&Enter_Date_YYYYMM'
)
GROUP BY
p_category,
CASE
WHEN ( issue_grp = 1 ) THEN '1'
ELSE '2/3 '
END,
srt,
order_date
)
ORDER BY
order_date,
p_category,
issue_group

ORDER BY, set a specific case to the first index?

Using SQL Server 2008...
I'm having some troubles in trying to order my rows in a specific order that I would like them to be ordered by. I've found a few examples that use the ORDER BY CASE clause, but am unsure whether using this method will produce the result that I want it to, thus I come to the community!
Here's what I have:
First, I select, if it exists, a distinct year that is equal to the current year:
IF EXISTS(SELECT DISTINCT [Year]
FROM Assessment WHERE ProjectCode = #ProjectCode AND [Year] = DATENAME(YEAR, GETDATE()))
SELECT DISTINCT [Year]
FROM Assessment WHERE ProjectCode = #ProjectCode
But, then I find some confusion in ordering the results. I'd like to set the current year to the first row returned using the ORDER BY clause, then order the rest of the returned years in a descending order, here's what I have so far:
ORDER BY (CASE WHEN [Year] = (DATENAME(YEAR, GETDATE())) THEN 1
ELSE 100 END) ASC, [Year] desc
Next, if the current year is not contained in the query, select each year and order by year descending.
ELSE
SELECT DISTINCT [Year]
FROM Assessment WHERE ProjectCode = #ProjectCode
ORDER BY [Year] desc
Thanks, in advance!
You don't need conditional statements here at all:
SELECT *
FROM (
SELECT DISTINCT [Year]
FROM Assessment
WHERE projectCode = #projectCode
) q
ORDER BY
CASE [Year] WHEN YEAR(GETDATE()) THEN 1 ELSE 2 END,
[Year]
will output the current year (if exists) first, the other later.
You're question isn't very clear because you don't specify what is broken or where you're having issues. From what I gather, however, you don't need an IF/ELSE. Instead you could do something like ...
SELECT DISTINCT [Year],
CASE [Year]
WHEN DATENAME(Year, GETDATE()) THEN 9999
ELSE [Year] END AS GarbageSoDistinctWorks
FROM Assessment
WHERE ProjectCode = #ProjectCode
ORDER BY
CASE [Year]
WHEN DATENAME(Year, GETDATE()) THEN 9999
ELSE [Year] END DESC
FYI ... i added the case to the select list as a throw away column to avoid the error I assume you're getting.. There are other ways, like a derived table, but for now this should work..
Msg 145, Level 15, State 1, Line 2
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
HTH,
-eric
Your example code appears to do what you describe. What problems are you having?
As a side note: You don't need the IF statement. By using the ORDER BY from your first example (with the CASE statement), you will get the correct results for both scenarios.
- If "this year" is in your data, it comes first. Everything else comes next in DESC order
- If "this year" isn't in your data, you just get everything else in DESC order