SQL functions, calculating a result based on other values - sql

I have a table with (Date(as date data type), Name, …) and i now want to add a column(on the right side), where it does something like this:
If Month =<6 (fill the cell in the row) with S+YY(YY being the Year in the date column) else (fill the cell with W+YY).
I came up with this:
SELECT *,
CASE
WHEN MONTH(Termin) < 6 THEN 'S' + YEAR(Termin)
ELSE 'W' + YEAR(Termin)
END as new_test FROM Prüfung; //Termin is the name of the column where the date format is in.
I am getting the error thingy saying that from is not in the right place?
CREATE TABLE "PRÜFUNG"
( "PRÜFUNG_ID" NUMBER(30,0),
"TERMIN" DATE,
"PRÜFUNGSFORM" VARCHAR2(30),
"RAUM_ID" NUMBER(30,0),
"MODUL_ID" NUMBER(30,0),
"LEHRVERANSTALTUNG_ID" NUMBER(30,0),
CONSTRAINT "PRÜFUNG_PK" PRIMARY KEY ("PRÜFUNG_ID")
USING INDEX ENABLE
)
This is code i used to generate the table.

One option is using EXTRACT with CASE:
SELECT
CASE WHEN EXTRACT(MONTH FROM TERMIN) <= 6
THEN 'S' || EXTRACT(YEAR FROM TERMIN)
ELSE 'W' || EXTRACT(YEAR FROM TERMIN) END AS new_test
FROM PRÜFUNG;
See the documentation of EXTRACT.
An example similar to your sample data here: db<>fiddle
If you need to select further columns, I highly recommend to do not use *, see here why, but to write a proper column selection.
For example
SELECT
TERMIN, PRÜFUNGSFORM,
CASE WHEN EXTRACT(MONTH FROM TERMIN) <= 6
THEN 'S' || EXTRACT(YEAR FROM TERMIN)
ELSE 'W' || EXTRACT(YEAR FROM TERMIN) END AS new_test
FROM PRÜFUNG;

You try use this
SELECT *,
CASE WHEN
EXTRACT(MONTH FROM TERMIN) <= 6 THEN
'S' ||TO_CHAR(TERMIN,'YY')
ELSE
'W' || TO_CHAR(TERMIN,'YY') END as new_test
FROM Prüfung;

Related

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

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!

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

Oracle SQL - Hour must be between 0 and 23 error

I am running the whole query and everything runs fine, until at the end I get the error(title) and the output should be like the excel image below. I have tried keeping hours as char and num and date, however I am still getting the error. Any help would be appreciated. Please feel free to ask questions and check the code in your tool. Thanks
with ht as(
select labno, birthdt, spectype,
--to_char(
((dtrecv - dtcoll)
+ ( to_date(nvl(tmrecv, '0000'), 'hh24mi')
- to_date(nvl(tmcoll, '0000'), 'hh24mi'))
) * 24
--, 'hh24:mi' )
as hours
from azmsds.sample_demog_view
where tmrecv is not null and tmcoll is not null and dtrecv is not null and dtcoll is not null
),
secondQuery AS (
select
ht.hours,
extract(year from ht.birthdt) as "YEAR",
extract (month from ht.birthdt) as "MONTH",
count(distinct ht.labno) as "initialDbsReceiptCount<1",
'~' AS EOL
from ht
where 1=1
and ht.hours is not null
--and month not null
AND ht.birthdt >= '01-JAN-12'
-- and hours <= 23
and ht.spectype in (1,5,7)
--and hours > 23
group by extract(year from ht.birthdt), extract (month from ht.birthdt), ht.hours
order by extract(year from ht.birthdt) desc
),
ThirdQuery AS (
SELECT
sq.year,
sq.month,
sq."initialDbsReceiptCount<1",
sq.eol
FROM secondQuery sq
WHERE 1=1
--AND sq.hours <= 24
)
select * from ThirdQuery
Seems to me you have some wrong data in iether tmrecv OR tmcoll...
if you do
select to_date('2500', 'hh24mi') from dual;
You will receive this error.
So I would start with trying the below selects to narrow down where the issue is
select to_date(nvl(tmrecv, '0000'), 'hh24mi') as hours
from azmsds.sample_demog_view
where tmrecv is not null and tmcoll is not null and dtrecv is not null and dtcoll is not null
select to_date(nvl(tmcoll, '0000'), 'hh24mi')) as hours
from azmsds.sample_demog_view
where tmrecv is not null and tmcoll is not null and dtrecv is not null and dtcoll is not null
One or the other of the above will give you the error, then you can examine the data from these fields to find the data that is causing you the error.
It appears you have invalid time values. This should help identify the bad ones.
select * from azmsds.sample_demog_view
where
tmrecv not like '[0-2][0-9][0-5][0-9]'
or tmcoll not like '[0-2][0-9][0-5][0-9]'
or not tmrecv between '0000' and '2359'
or not tmcoll between '0000' and '2359'

SQL Month comparison to declared variable

select
sc.locationid, --here to get a result
(
if month(date()) between 8 and 12 then #semTerm = 'S1'
else #semTerm = 'S2'
end if
)as #semTerm
from student_class sc
where #semTerm = sc.semester
;
In db2 student management system. Read only access. Desired outcome is If Jan thru June, S2 else if Aug thru Dec, S1. Trying to setup a variable based on the current date stamp where the month is segregated then assigned to a variable then compared against a column in student_class table.
Have tried case statements as well with no luck. Unable to declare #semTerm without error above select statement. Looked at where clause solution also. Am I out in left field? Seems simple but struggling with the syntax. Part of a larger statement with locationID as one column in student_class.
You can't really use an IF statement in a simple SELECT statement, you must use CASE:
select
sc.locationid, --here to get a result
case
when month(current date) between 8 and 12 then 'S1'
when month(current date) between 1 and 6 then 'S2'
else ''
end as semTerm
from
student_class sc
If you want to find only the students for the current semester, then you would want to move the CASE statement into the WHERE clause:
select
sc.locationid, --here to get a result
sc.semester,
...
from
student_class sc
where
sc.semester = case
when month(current date) between 8 and 12 then 'S1'
when month(current date) between 1 and 6 then 'S2'
end
A CASE expression is generally the way to implement conditional logic in a SELECT statement. However, it would be more efficient if you didn't have to recalculate it on every row, right?
One approach would be to "precalculate" it in a common table expression, and join to that as your selection criteria:
with v (semester) as
( values
case
when month(current date) > 7 then 'S1'
when month(current date) < 7 then 'S2'
else null
end
)
select
sc.locationid,
sc.semester,
...
from
student_class sc
join
v on sc.semester = v.semester;
OR
If you you find that this current semester value would be useful in many other places, another approach could be to create a 'global session variable' to hold the value. (except on z/OS)
create or replace variable
v_sememster char(2)
default
case
when month(current date) > 7
then 'S1'
when month(current date) < 7
then 'S2'
else null
end;
Then you can have a very simple query:
select
sc.locationid,
sc.semester,
...
from
student_class sc
where
sc.semester = v_semester;