How to have CASE statement look at previous records in the statement - tsql

I have the following code generating a case statement in which I would like all future time periods to return 'Graduated' if the student graduated in a previous time period. Here is the current code:
SELECT DISTINCT
Z1.StudentID,
Z1.AcadLevel,
Z1.StudentAcadLevel,
Z1.StudentCohortStartDate,
Z1.PeriodID,
Z2.CourseTimePeriod,
Z3.DegreeTimePeriod,
CASE
WHEN Z1.PeriodID = '0' THEN 'CohortStart'
WHEN Z3.DegreeTimePeriod <= Z1.PeriodID THEN 'Graduated'
WHEN Z1.PeriodID = Z2.CourseTimePeriod THEN 'Retained'
WHEN Z2.CourseTimePeriod IS NULL THEN 'Churned'
ELSE 'Fix Me'
END AS TimePeriodStatus
FROM Z_Retention_StudentTimePeriodStatus Z1
LEFT OUTER JOIN Z_Retention_StudentCourseRegistrations Z2 ON Z2.StudentID = Z1.StudentID AND Z2.STC_ACAD_LEVEL = Z1.AcadLevel AND Z2.CourseTimePeriod = Z1.PeriodID
LEFT OUTER JOIN Z_Retention_StudentDegree Z3 ON Z3.StudentID = Z1.StudentID AND Z3.DegreeAcadLevel = Z1.AcadLevel AND Z3.DegreeTimePeriod = Z1.PeriodID
ORDER BY Z1.StudentID, Z1.PeriodID, Z2.CourseTimePeriod
In the attached image, I'm hoping to add a line to the case statement that would make the highlighted rows return 'Graduated' rather than 'Churned'.

Related

How to decrease Query Time - Postgresql

PostgreSQL 9.6.9, compiled by Visual C++ build 1800, 64-bit
I have a question about query time. This 'view' has +1M data and when you execute select*from view , its query time is +400 seconds. On my query, it returns 10k data and query time is around 8-10 seconds. I am looking for a way to decrease it to 1 or 2 seconds. I tried changing or deleting things in my where or select clause, but only solution i came up with is limiting between "time" part.
If anyone know a better solution, that would be appreciated!
Thanks,
Can
Note: This view contains three different tables(cl_segments,cl_participants,cl_party_info).
I could not find a definition for those tables but i will add pictures of indexes and fields. Please let me know if you need any additional information.
clparticipantfields
clparticipantindexes
clpartyinfofields
clpartyinfoindexes
clsegmentsfields
clsegmentsindexes
EXPLAIN ANALYZE BUFFERS
select distinct on (clsgview.call_id)clsgview.call_id as call_id,
case when clsgview.src_dn_type = '0' and clsgview.dst_dn_type = '0' then
right(clsgview.src_dn,11)
when clsgview.src_dn_type = '1' and clsgview.dst_dn_type = '0' then
right(clsgview.src_caller_number,11)
when clsgview.src_dn_type = '0' and clsgview.dst_dn_type = ANY (ARRAY[1,12,13]) then
right(clsgview.src_dn,11) end as from,
case when clsgview.src_dn_type = '0' and clsgview.dst_dn_type = '0' then
right(clsgview.dst_dn,11)
when clsgview.src_dn_type = '1' and clsgview.dst_dn_type = '0' then
right(clsgview.dst_dn,11)
when clsgview.src_dn_type = '0' and clsgview.dst_dn_type = ANY (ARRAY[1,12,13]) then
right(clsgview.dst_display_name,11) end as to,
case when clsgview.act = ANY (ARRAY[5,6]) and clsgview.dst_dn_type != ANY (ARRAY[12]) then (end_time-start_time) else '00:00:00' end as talktime
from
( SELECT s.call_id,
s.id AS seg_id,
s.type AS seg_type,
s.seq_order AS seg_order,
s.start_time,
s.end_time,
si.dn_type AS src_dn_type,
si.dn AS src_dn,
si.display_name AS src_display_name,
si.firstlastname AS src_firstlastname,
si.caller_number AS src_caller_number,
dp.start_time AS dst_start_time,
dp.answer_time AS dst_answer_time,
dp.end_time AS dst_end_time,
dp.billing_rate AS dst_billing_rate,
di.dn_type AS dst_dn_type,
di.dn AS dst_dn,
di.display_name AS dst_display_name,
di.firstlastname AS dst_firstlastname,
di.caller_number AS dst_caller_number,
di.dn_class AS dst_dn_class,
s.action_id AS act,
ai.dn_type AS act_dn_type,
ai.dn AS act_dn,
ai.display_name AS act_display_name,
ai.firstlastname AS act_firstlastname
FROM ((((((cl_segments s
JOIN cl_participants sp ON ((sp.id = s.src_part_id)))
JOIN cl_participants dp ON ((dp.id = s.dst_part_id)))
JOIN cl_party_info si ON ((si.id = sp.info_id)))
JOIN cl_party_info di ON ((di.id = dp.info_id)))
LEFT JOIN cl_participants ap ON ((ap.id = s.action_party_id)))
LEFT JOIN cl_party_info ai ON ((ai.id = ap.info_id)))
order by seg_id desc
) as clsgview
where clsgview.src_dn_type = ANY (ARRAY[0,1])
and clsgview.dst_dn_type = ANY (ARRAY[0,1,12,13])
and clsgview.act != ANY (ARRAY[1]) and ((clsgview.act = ANY (ARRAY[15,101,102,103,107,400,409,418,419,421,423])) or (clsgview.act = ANY (ARRAY[5,6]) and clsgview.dst_dn_type = ANY (ARRAY[12])))
and clsgview.dst_display_name not like '*%' and clsgview.dst_caller_number not like '*%'
and (clsgview.src_dn = '1004' or clsgview.dst_dn = '1004')
and start_time::date BETWEEN '2020-01-01'::DATE and now()::DATE
order by clsgview.call_id desc

How to select from subquery if column contains a specific value in postgre

I would like to ask if it is possible to select again from a result set if a column contains a specific value?
For example, from the below query I want to select it as subquery and check if that subquery's first column contains both 2 and 3 result. Otherwise, no values should be return.
select e.evaluator_id, ROUND(avg(cast(e.rating_score as int))::numeric,1)::varchar, c.q_category_name
from tms.t_evaluation e
inner join tms.m_q_category c
on e.nendo=c.nendo
and e.q_category_id = c.q_category_id
and c.delete_flg = '0'
inner join tms.m_q_subcategory qs
on e.q_category_id = qs.q_category_id
and e.q_subcategory_id = qs.q_subcategory_id
and c.nendo = qs.nendo
and qs.delete_flg = '0'
where e.nendo = '2018'
and e.empl_id = 'empl05'
and e.delete_flg = '0'
and e.evaluator_id in ('2' , '3')
group by e.empl_id, e.nendo, e.q_category_id,
c.q_category_name, e.evaluator_id, e.history_no
Result contains both 2 and 3 in first column. Is this possible?
select e.evaluator_id, ROUND(avg(cast(e.rating_score as int))::numeric,1)::varchar, c.q_category_name
from tms.t_evaluation e
inner join tms.m_q_category c
on e.nendo=c.nendo
and e.q_category_id = c.q_category_id
and c.delete_flg = '0'
inner join tms.m_q_subcategory qs
on e.q_category_id = qs.q_category_id
and e.q_subcategory_id = qs.q_subcategory_id
and c.nendo = qs.nendo
and qs.delete_flg = '0'
where e.nendo = '2018'
and e.empl_id = 'empl05'
and e.delete_flg = '0'
and e.evaluator_id in (select case when evaluator_id=2 or evaluator_id=3 then evaluator_id else null from t_evaluation order by evaluator_id asc)
group by e.empl_id, e.nendo, e.q_category_id,
c.q_category_name, e.evaluator_id, e.history_no

how can use loop or IF in case when statements in postgresql

select distinct
x.vrgid, x.Weights, x.geom
from
(select
-- postcodes.id as postcodeid ,,fishnet.geom as geom
fishnet.gid as vrgid,
fishnet.geom as geom,
CASE WHEN
st_intersects(centroids.geom, urban.geom) and counts.nonurbancells != 0
THEN 0.95 :: numeric / counts.urbancells -------1st case
WHEN st_intersects(centroids.geom, urban.geom) and counts.nonurbancells = 0
THEN 1.00 :: numeric / counts.urbancells ---2ndcase
WHEN Not st_intersects(centroids.geom, urban.geom) = fishnet.gid :: boolean and counts.nonurbancells != 0
THEN 0.05 :: numeric / counts.nonurbancells ----3rd case
ELSE 0
END AS Weights
from vrg.urban_nonurban_count_new as counts
inner join vrg.gfk_2016_id_5_digit_pcd_areas2013_projected as postcodes on postcodes.id = counts.postid
right outer join vrg.rdsid_86_quadgrid_centroids as centroids on st_contains(postcodes.geom, centroids.geom)
left outer join vrg.rdsid86_quadgrid AS fishnet on fishnet.gid = centroids.gid
right outer join vrg.rdsid86_katrisk_poly_projected as urban on st_intersects(urban.geom, fishnet.geom)
where postcodes.id = '42395') as x
I have several case statements in my PL/Pgsql function in which the I get duplicate rows (with duplicate vrgids). Below is the query result
Here (the marked row) with id 7192 is the result of 1st case statement(refer the query)
What I would like to do is use loop or if condition to remove the vrgid and corresponding weights from the result once the 1st case statement is true.
So thet I won't get duplicate records. How is it possible?
May be I should use a condition in 3rd statement to result out the vrgids not present in 1st case statement.

Returning distinct columns from left outer join in db2

SELECT
nzy.NZPYYD
,nzy.NZZSYG
,nzy.NZJRYG
,acn.ANITCD
FROM
ACNTRA acn
LEFT OUTER JOIN NZYTFL nzy
ON (
nzy.NZCNO1 = acn.ANCNO1
AND nzy.NZCNO2 = acn.ANCNO2
AND nzy.NZCNO3 = acn.ANCNO3
AND nzy.NZCNO4 = acn.ANCNO4
AND nzy.NZCNO5 = acn.ANCNO5
AND nzy.NZSLKI = acn.ANSLKI
AND nzy.NZDLTM = ''
)
WHERE
acn.ANDLTM = ''
AND acn.ANTKCD = '1029'
AND nzy.NZTXKB = 1
The problem here is it gives 2 rows result.I want to get one unique row from the result of left outer join .Any help?
If both rows are identical, try
SELECT DISTINCT
nzy.NZPYYD
,nzy.NZZSYG
,nzy.NZJRYG
,acn.ANITCD
If not, you can try to SUM(), CONCAT(), MAX() or whatever the column with different values.
Difficult to be more precise without a sample output.

crytal report count total records

Im using query in crystal report like:
if({?User Name}) <>"ALL"
then
{COMN_USER_RESP_LINK_T.APPL_USER_NAME}={?User Name}
else
{COMN_USER_RESP_LINK_T.APPL_USER_NAME} ={COMN_USER_RESP_LINK_T.APPL_USER_NAME}
and
{COMN_USER_RESP_LINK_T.ENABLED}="Y"
this is actual query in sql:
SELECT
C.APPL_USER_NAME,
A.RESP_NAME,
B.MENU_NAME,
B.DESCRIPTION,
B.MODULE_NAME,
C.APPL_RESP
FROM COMN_RESPONSIBILITY_T A,
COMN_RESP_MENU_LINK_T B,
COMN_USER_RESP_LINK_T C
WHERE A.COMP_CODE = B.COMP_CODE
AND B.COMP_CODE = C.COMP_CODE
AND C.COMP_CODE = A.COMP_CODE
AND A.RESP_NAME = B.RESP
AND C.APPL_RESP = A.RESP_NAME
AND B.ENABLED = 'Y'
AND C.APPL_USER_NAME = c.APPL_USER_NAME
CASE #ACCT_CODE_FROM
WHEN 'ALL' THEN C.APPL_USER_NAME
ELSE #ACCT_CODE_FROM
END
ORDER BY APPL_USER_NAME,
RESP_NAME
I should select user name in parameter field(?user name), if I select ALL then I have to show all records ({COMN_USER_RESP_LINK_T.APPL_USER_NAME})
is the above query correct?
I would probably rephrase that as something like:
SELECT C.APPL_USER_NAME, A.RESP_NAME, B.MENU_NAME, B.DESCRIPTION,
B.MODULE_NAME, C.APPL_RESP
FROM COMN_RESPONSIBILITY_T A
INNER JOIN COMN_RESP_MENU_LINK_T B ON A.COMP_CODE = B.COMP_CODE
AND A.RESP_NAME = B.RESP
INNER JOIN COMN_USER_RESP_LINK_T C ON B.COMP_CODE = C.COMP_CODE
AND C.APPL_RESP = A.RESP_NAME
WHERE ((#ACCT_CODE_FROM = 'ALL') AND (B.ENABLED = 'Y'))
OR (C.APPL_USER_NAME = #ACCT_CODE_FROM)
ORDER BY APPL_USER_NAME, RESP_NAME
This gets you the details for either:
when ALL is selected, all accounts that are enabled; or
just the user code entered
i don't read your code because it is very dirty! but i think you can use SelectionFormula in crystal report. Certainly you can set it in code :
crystalReportViewer1.SelectionFormula ="(({?User Name}= 'ALL') AND ({B.ENABLED} = 'Y'))
OR ({C.APPL_USER_NAME} = #ACCT_CODE_FROM)"