SQL Server Select one from multiple rows based on calculation - sql-server-2008-r2

I'm trying to find the greatest number of days (and the reviewer's badge number) it took one of several reviewers to approve a particular document in a workflow. For example, I have a table that holds several workflow approval steps (submitter, manager, controller, QA), along with their badge numbers, and date they approved. The table is called "Workflow" and has those four workflow steps mentioned above as records in the table, and the main table Design that has a one-to-many relationship with Workflow.
I'm trying to determine how many days for the longest review step (number of days), and the badge number of the reviewer for that step (who is holding up the approval workflow, basically). I've been trying to set independent variables to be used later, but not sure how to also set the badge number and I'm confused. I have tried CASE, IIF, and COALESCE but am not having any luck because I don't want the first true value returned and then stop, I want it to continue to evaluate all the steps. Here is an example of my SQL:
declare #managerTime int = 0
declare #controllerTime int = 0
declare #qaTime int = 0
SET #managerTime = (SELECT DATEDIFF(day, manager.BadgeDate, submitter.BadgeDate)
from Design d
left outer join Workflow submitter on (d.DCRId = submitter.DCRId and submitter.RoleName = 'Submitter')
left outer join Workflow manager on (d.DCRId = manager.DCRId and manager.RoleName = 'System Manager')
SET #controllerTime = (SELECT DATEDIFF(day, controller.BadgeDate, manager.BadgeDate)
from Design d
left outer join Workflow manager on (d.DCRId = manager.DCRId and manager.RoleName = 'System Manager')
left outer join Workflow controller on (d.DCRId = controller.DCRId and controller.RoleName = 'DCR Controller')

This is how I would do it:
Create table WorkflowDefinition with flow definiton:
Source Destination Description
Submitter System Manager Submitter -> System Manager
System Manager DCR Controller System Manager -> DCR Controller
DCR Controller QA DCR Controller -> QA
Now we use this table to join workflow elements and calculate greatest number of days:
SET #MaxTime = (SELECT MAX(DATEDIFF(day, source.BadgeDate, destination.BadgeDate))
from Design d
inner join Workflow source on d.DCRId = source.DCRId
inner join WorkflowDefinition flow on source.RoleName = flow.source
inner join Workflow destination on d.DCRId = destination.DCRId
and destination.RoleName = flow.destination
)
When we have this value we can select all workflow elements which took this exact number of days to complete:
Select
destination.BadgeNumber
from Design d
inner join Workflow source on d.DCRId = source.DCRId
inner join WorkflowDefinition flow on source.RoleName = flow.source
inner join Workflow destination on d.DCRId = destination.DCRId
and destination.RoleName = flow.destination
where DATEDIFF(day, source.BadgeDate, destination.BadgeDate) = #MaxTime
If you want to know max value of days for every type of step separately then we can do something like this: Calculate max value of days per step type and put this into temp table:
SELECT
MAX(DATEDIFF(day, source.BadgeDate, destination.BadgeDate)) as maxDays,
flow.Description as StepDescription
into #tmp
from Design d
inner join Workflow source on d.DCRId = source.DCRId
inner join WorkflowDefinition flow on source.RoleName = flow.source
inner join Workflow destination on d.DCRId = destination.DCRId
and destination.RoleName = flow.destination
group by flow.Description
And now use this table to select steps matching max number of days and step description:
Select
destination.BadgeNumber
from Design d
inner join Workflow source on d.DCRId = source.DCRId
inner join WorkflowDefinition flow on source.RoleName = flow.source
inner join Workflow destination on d.DCRId = destination.DCRId
and destination.RoleName = flow.destination
inner join #tmp on DATEDIFF(day, source.BadgeDate, destination.BadgeDate) = maxDays and StepDescription = flow.Description

I ended up tackling this from the "many" table (Workflow), instead of the Design table. I used the following SQL which got me the results I was after. Thank you all for trying to make sense of my ramblings.
select
w.DesignId,
w.RoleName,
w.BadgeNumber,
w.BadgeDate,
DATEDIFF(day,
(select x.BadgeDate from Workflow x
where x.BadgeDate is not null
and x.DesignId = w.DesignId
and x.StepOrder = w.StepOrder - 1),
(select b.BadgeDate from Workflow b
where b.BadgeDate is not null
and b.DesignId = w.DesignId
and b.StepOrder = w.StepOrder))
as StepDuration,
w.StepOrder,
TotalDuration = DATEDIFF(day,
(select y.BadgeDate from Workflow y
where y.RoleName = 'Submitter'
and y.DesignId = w.DesignId),
(select v.BadgeDate from Workflow v
where v.RoleName = 'Approver'
and v.DesignId = w.DesignId)),
d.VersionNumber,
d.Title
from Workflow w
inner join Design d on d.DesignId = w.DesignId

Related

T-SQL Question for Getting One Customer Type When There Can be More Than One Value

We have an organization that can have more than one customer type basically. However, what a user wants to see is either the partner or direct type (customer type is either Direct, Partner1, Partner2, or Partner3 but can be direct plus a partner value but only can be one of the partner values). So if a customer is both (ex: Direct and Partner1) they just want the type that is a partner (ex: Partner1). So I tried splitting out partners only into one temp table from a few tables joining together different org data. I have the same query without any limit pulling into a different temp table. Then I calculate count and put that into a temp table. Then I tried gathering data from all the temp tables. That is where I run into trouble and lose some of the customers where the type is direct (I have a image link below for a directcustomer and a customer who is both). I have been out of SQL for a bit so this one is throwing me...I figure the issue is the fact that I have a case statement referencing a table that a direct customer will not exist in (#WLPO). However I am not sure how to achieve pulling in these customers while also only selecting which partner type it is for a customer that has a partner and is also direct. FYI using MSSMS for querying.
If OBJECT_ID('tempdb..#WLPO') IS NOT NULL
DROP TABLE #WLPO
IF OBJECT_ID('tempdb..#org') IS NOT NULL
DROP TABLE #org
IF OBJECT_ID('tempdb..#OrgCount') IS NOT NULL
DROP TABLE #OrgCount
IF OBJECT_ID('tempdb..#cc') IS NOT NULL
DROP TABLE #cc
Select
o.OrganizationID,
o.OrganizationName,
os.WhiteLabelPartnerID,
s.StateName
INTO #WLPO
from [Org].[Organizations] o
join [Org].[OrganizationStates] os on o.OrganizationID=os.OrganizationID --and os.WhiteLabelPartnerID = 1
join [Lookup].[States] s on os.StateID = s.StateID
join [Org].[PaymentOnFile] pof on pof.OrganizationID=o.OrganizationID
where os.WhiteLabelPartnerID in (2,3,4)
and os.StateID in (1, 2, 3)
and o.OrganizationID = 7613
select * from #WLPO
Select
o.OrganizationID,
o.OrganizationName,
os.WhiteLabelPartnerID,
s.StateName
INTO #org
from [Org].[Organizations] o
join [Org].[OrganizationStates] os on o.OrganizationID=os.OrganizationID --and os.WhiteLabelPartnerID = 1
join [Lookup].[States] s on os.StateID = s.StateID
join [Org].[PaymentOnFile] pof on pof.OrganizationID=o.OrganizationID
where 1=1--os.WhiteLabelPartnerID = 1
and os.StateID in (1, 2, 3)
and o.OrganizationID = 7613
select * from #org
Select
OrganizationID,
count(OrganizationID) AS CountOrgTypes
INTO #OrgCount
from #org
where OrganizationID = 7613
group by OrganizationID
select * from #OrgCount
Select distinct
ct.OrganizationID,
ok.OrganizationName,
ct.CountOrgTypes,
case when ct.CountOrgTypes = 2 then wlp.WhiteLabelPartnerID
when ct.CountOrgTypes = 1 then ok.WhiteLabelPartnerID
END AS CustomerTypeCode,
case when ct.CountOrgTypes = 2 then wlp.StateName
when ct.CountOrgTypes = 1 then ok.StateName END As OrgState
INTO #cc
from #org ok
left join #WLPO wlp on wlp.OrganizationID=ok.OrganizationID
join #OrgCount ct on wlp.OrganizationID=ct.OrganizationID
select * from #cc
Select
OrganizationID,
OrganizationName,
CountOrgTypes,
case when CustomerTypeCode = 1 then 'Direct'
when CustomerTypeCode = 2 then 'Partner1'
when CustomerTypeCode = 3 then 'Partner2'
when CustomerTypeCode = 4 then 'Partner3' ELSE Null END AS CustomerType,
OrgState
from #cc
order by OrganizationName asc
DirectCustomer
CustomerwithBoth

The multi-part identifier could not be bound - SQL Server 2016

SELECT clm.CLCL_PAYEE_PR_ID, clm.SBSB_CK, clm.CLCL_ID, clm.clcl_id_adj_to,clm.clcl_id_adj_from, clm.CLCL_PAID_DT
FROM ODW.DW.fac_cmc_clcl_claim CLM
INNER JOIN ODW.DW.fac_cmc_meme_member MEME ON MEME.meme_ck = CLM.meme_ck
INNER JOIN ODW.DW.fac_cmc_mepe_prcs_elig MEPE ON MEPE.meme_ck = MEME.meme_ck
INNER JOIN ODW.DW.fac_cmc_mepr_prim_prov MEPR ON MEPE.meme_ck = MEPR.meme_ck AND CLM.clcl_prpr_id_pcp = MEPR.prpr_id
INNER JOIN ODW.DW.fac_cmc_sbsb_subsc SBSB ON MEME.sbsb_ck = SBSB.sbsb_ck
INNER JOIN ODW.DW.fac_cmc_prpr_prov PROV ON MEPR.prpr_id = PROV.prpr_id AND PROV.prpr_mctr_prty = 'RISK'
INNER JOIN ODW.DW.fac_cmc_prer_relation PRER ON PRER.prpr_id = MEPR.prpr_id
INNER JOIN ODW.DW.fac_cmc_plds_plan_desc PLDS ON MEPE.cspi_id = PLDS.cspi_id
INNER JOIN ODW.DW.fac_cmc_pdds_prod_desc PDDS ON MEPE.pdpd_id = PDDS.pdpd_id
WHERE CLM.clcl_paid_dt BETWEEN '2019-12-24 00:00:00.000' AND '2019-12-30 23:59:59.997'
AND CLM.clcl_cur_sts = '02'
AND CLM.clcl_cl_type = 'M'
AND CLM.clcl_cl_sub_type = 'H'
AND CLM.grgr_ck IN (46)
AND MEPR.grgr_ck IN (46)
AND MEPE.grgr_ck IN (46)
AND MEPE.mepe_elig_ind = 'Y'
AND CLM.clcl_low_svc_dt BETWEEN MEPE.mepe_eff_dt AND MEPE.mepe_term_dt
AND CLM.clcl_low_svc_dt BETWEEN MEPR.mepr_eff_dt AND MEPR.mepr_term_dt
AND SBSB.grgr_ck IN (46)
AND PRER.prer_prpr_entity = 'I'
AND PRER.prer_prpr_id IN ('64456546')
AND (PLDS.plds_desc LIKE '%risk%' OR PDDS.pdds_desc LIKE '%risk%');
This query runs in PROD with different variables which substitute the value of the hard coded values. It runs around 100 times per day in PROD and on some days some of the runs fail due to this error:
The multi-part identifier "PDDS.pdds_desc" could not be bound
Please note that all the joins are being done on views.
When I re-run the failed process, it succeeds the second time with no changes to the underlying query.
Can anyone suggest what could be the issue. Also, any performance optimization suggestions for this query query will be appreciated.
Thanks!

Pass order by clause from Java in Jasper Report

I am using latest version of Jasper soft studio to design Jasper reports. I want to pass order by clause to jasper report based on certain criteria from Java. Can you please guide as how to append parameter(containing order by clause from Java) in the report query?
Query
with tmp as (
select d.gl_code, nvl(sum(d.debit),0)- nvl(sum(d.credit),0) as simple
from gl_forms g,gl_voucher_detail d,financial_year f
where g.voucher_no = d.voucher_no
and f.fid = $P{P_FID}
and g.voucher_date >= to_date('01-07-'+f.start_year,'dd-MM-yyyy') and g.voucher_date < $P{P_FROM}
and g.post=1
group by d.gl_code)
select g.voucher_no,
g.voucher_date,
g.voucher_type,
g.remarks remarks,
d.sr_no,
c.account_name,
d.debit,
d.credit,
d.narration narration,
c.account_code,
c.account_name || ' - ' || c.account_code Account,
(select name from company) name,
nvl((o.debit-o.credit),0) + nvl(tmp.simple,0) opening
from gl_voucher_detail d
join gl_forms g
on g.voucher_no = d.voucher_no
and g.post=1
and g.voucher_date between $P{P_FROM} and $P{P_TO}
left outer join opening_balances o
on d.gl_code = o.account_code
and o.fid = $P{P_FID}
right outer join chart_of_account c
on c.account_code = d.gl_code
left outer join tmp
on c.account_code = tmp.gl_code
where c.account_level=4
and c.active=1
and c.account_code = CASEWHEN($P{P_ACCOUNT}='%',c.account_code,$P{P_ACCOUNT})
Order by clause shall be one among these below two based on front fields selection:
order by c.account_name, g.voucher_date,g.voucher_no,d.sr_no
order by c.debit+c.credit desc

SELECT attribute with MIN value from set of attribute instances that are part of specific row?

I know my question is probably very vague and hard to understand at first glance, and i've sat 30 minutes thinking about a proper title. However my database knowledge is very limited so I have a hard time formulating myself properly yet.
It is part of a school assignment I'm currently doing, where the following is what I'm trying to achieve:
and an ER diagram I made of the system:
What I'm trying to accomplish is, selecting the quantity of the component within the computer_system that has the lowest quantity (current stock) so that I in the dataset I am printing out, am able to state exactly how many of each computer_system the store is able to sell, based on the lowest current quantity of any component the computer_system consists of.
This is the query that i am currently working with to accomplish it, but I've had multiple problems with quantity being ambiguous and other errors every time I try to make a fix. I have consulted a dozen of friends from class, but without luck.
SELECT
computer_system.NAME,
cpu.name as cpu,
gpu.name as gpu,
board.name as mainboard,
pccase.name as pc_case,
ram.name as ram,
component.quantity as qty,
(cpu.price *1.3+ board.price*1.3 + pccase.price*1.3 + ram.price*1.3 + gpu.price*1.3) as computer_system_price
FROM computer_system, component
join component cpu on cpu.id = computer_system.cpu
join component gpu on gpu.id = computer_system.gpu
join component board on board.id = computer_system.mainboard
join component pccase on pccase.id = computer_system.pc_case
join component ram on ram.id = computer_system.ram
JOIN component qty ON qty.quantity = (SELECT MIN(component.quantity) FROM component WHERE component.id IN
(computer_system.pc_case,
computer_system.mainboard,
computer_system.cpu,
computer_system.gpu,
computer_system.ram))
The following code fixed it for me:
SELECT computer_system.name AS "System name",
cpu.name AS "CPU",
gpu.name AS "GPU",
pc_case.name AS "Case",
mainboard.name AS "Mainboard",
ram.name AS "RAM",
FLOOR((cpu.price + mainboard.price + pc_case.price + ram.price + coalesce(gpu.price, 0))*1.3/100)*100+99 AS "System price",
SYSTEM.maxamount
FROM computer_system
join (SELECT name,
id,
price
FROM component) AS cpu
ON cpu.id = computer_system.cpu
left join (SELECT name,
id,
price
FROM component) AS gpu
ON coalesce(gpu.id,0) = computer_system.gpu
join (SELECT name,
id,
price
FROM component) AS pc_case
ON pc_case.id = computer_system.pc_case
join (SELECT name,
id,
price
FROM component) AS mainboard
ON mainboard.id = computer_system.mainboard
join (SELECT name,
id,
price
FROM component) AS ram
ON ram.id = computer_system.ram
join (SELECT computer_system.name,
Min(component.quantity) AS maxamount
FROM computer_system,
component
WHERE computer_system.cpu = component.id
OR computer_system.gpu = component.id
OR computer_system.mainboard = component.id
OR computer_system.pc_case = component.id
OR computer_system.ram = component.id
GROUP BY computer_system.name) AS SYSTEM
ON SYSTEM.name = computer_system.name;

How to create variables in derived table using different conditions

I want to generate a table and all the variables I need are from a derived temporary table. Now, I need to calculate the time differences under different conditions, and I need to deal with 2 questions:
1. how to create variables in derived table.
2. how to split a variable into 2 variables using different conditions.
Please note that the sql statement I provide below is the simplified statement and please pay attention to the comments which will help you understand the question.
Thanks in advance for any tips.
Here is the SQL statement:
Select id, name, offline_time, Process_time from
## in the derived table, use the difference of createon in table a and b to calculte the offline_time and Process_time ##
## when {a.id = st.id AND a.activityid = 5008 and a.sessiontype = 7} a.creaton = a.creaton1 ##
## when {b.activityid = 5011} b.creaton = b.creaton1 ##
(select
(UNIX_TIMESTAMP(MAX(a.createdon)) - UNIX_TIMESTAMP(MAX(b.createdon))) as 'Offline_Time',
(UNIX_TIMESTAMP(MAX(a.createdon1)) - UNIX_TIMESTAMP(MAX(b.createdon1))) as 'Process_Time',
q.id,
q.name,
a.sessiontype
FROM tv_sessiontimer st
LEFT JOIN sessionactivity_log a ON (a.id = st.id AND a.activityid in (5004,5008) and a.sessiontype IN (3,4,5,6,7))
LEFT JOIN sessionactivity_log b ON (a.ssessionId = b.sessionId AND a.id = b.id AND b.activityid in (5003,5011))
INNER JOIN tv_offline_request q ON q.id = a.sessionid
LEFT JOIN tv_subject sub ON (sub.id = q.subjectid AND sub.SortKey > 10800 AND sub.sortkey < 30200)
)