SQL - Return fields ONLY containing met requirement - sql

I am trying to do the following:
Assign a Y/N flag as Prior Approval which includes all policies that are policies with BI limit 25/50 and PD limit 25 and no other coverage.
So this code satisfies the first requirements:
SELECT DISTINCT
PolNum
FROM Results_Vehicle
WHERE ( CovCode = 'BI'
AND CovLimit = '25/50'
)
OR ( CovCode = 'PD'
AND CovLimit = '25'
)
I can't figure out how to not include records that have other coverage. So basically for each policy they can have CovCodes of UMBI, COL, REN, BI, PD, etc. But the flag should only give a Y if for that PolNum they ONLY have BI or PD as CovCode and the CovLimit defined above.
So also I'll need to put it in the Y/N format as follows, obviously this only satisfies the first part of the requirement:
SELECT CASE WHEN ( CovCode = 'BI'
AND CovLimit = '25/50'
)
OR ( CovCode = 'PD'
AND CovLimit = '25'
) THEN 'Y'
ELSE 'N'
END AS PriorApproval
FROM Results_Vehicle

How about this query below. The union query gives you a combined list of all the PolNum's that have that type of coverage, so then you do a not in to give you all the policy numbers that AREN'T in that list, and then you do a not in on that list, which should leave you with the PolNum's that only have the desired coverage and no other coverage.
SELECT CASE WHEN
(
(CovCode = 'BI' AND CovLimit = '25/50')
OR
(CovCode = 'PD' AND CovLimit = '25')
and PolNum not in
(
select PolNum from Results_Vehicle as r1 where PolNum not in
(
select PolNum from Results_Vehicle as r2
where CovCode = 'BI' and CovLimit = '25/50'
union
select PolNum from Results_Vehicle as r3
where CovCode = 'PD' AND CovLimit = '25'
)
)
) THEN 'Y'
ELSE 'N'
END AS PriorApproval
FROM Results_Vehicle

Related

Divide the results of two select queries

I have two SQL count queries that on their own work fine, they are:
SELECT count(*) AS TOTAL_PROGRESS_BY_LINE_
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C'
RESULT: TOTAL_PROGRESS_BY_LINE_ = 26
SELECT count(*) AS TOTAL_LINES_BY_PROJECT_
FROM dbo.PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234'
RESULT: TOTAL_LINES_BY_PROJECT_ = 130
Now how to do I add to the query to get the percentage of 26/130??
I have a new query to go along with how to get percentages.
Here it is:
SELECT ISOGEN_LINE_PROGRESS_, PROJECT_NUMBER_,
CASE
WHEN ISOGEN_LINE_PROGRESS_ = 'A' THEN 'NOT IN MODEL'
WHEN ISOGEN_LINE_PROGRESS_ = 'B' THEN 'ROUGHED IN'
WHEN ISOGEN_LINE_PROGRESS_ = 'C' THEN 'PARTIAL CHECK'
WHEN ISOGEN_LINE_PROGRESS_ = 'D' THEN 'READY FOR FINAL CHECK'
WHEN ISOGEN_LINE_PROGRESS_ = 'E' THEN '100% COMPLETE'
WHEN ISOGEN_LINE_PROGRESS_ = '0' THEN 'ISSUE FOR CONSTRUCTION'
END AS PROGRESS_PER_LINE_
FROM PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234'
ORDER BY ISOGEN_LINE_PROGRESS_
this brings back results below:
ISOGEN_LINE_PROGRESS_ PROJECT_NUMBER_ PROGRESS_PER_LINE_
A PJ001234 NOT IN MODEL
B PJ001234 ROUGHED IN
C PJ001234 PARTIAL CHECK
D PJ001234 READY FOR FINAL CHECK
If I remove the Distinct from my query there are obviously multiple rows for each level of progress. How do I add to the above distinct query to have a column at the end with the rate or percent of each level of progress compared to the overall number of lines?
Select them as a subquery.
By default the result will be an integer because count(*) returns an int. For a decimal result convert to a decimal.
SELECT (
SELECT CONVERT(decimal(9,2),COUNT(*)) AS TOTAL_PROGRESS_BY_LINE_
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C'
) / (
SELECT CONVERT(decimal(9,2),COUNT(*)) AS TOTAL_LINES_BY_PROJECT_
FROM dbo.PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234'
)
You may use conditional aggregation and simple division in one query:
select
100.0 *
count(
case when ISOGEN_LINE_PROGRESS_ = 'C'
then 1
end
)
/
nullif(count(
case when PROJECT_NUMBER_ = 'PJ001234'
then 1
end
), 0) as rate_
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C'
or PROJECT_NUMBER_ = 'PJ001234'
DECLARE #firstone INT;
DECLARE #secondone INT;
SELECT #firstone = count(*)
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C';
SELECT #secondone = count(*)
FROM dbo.PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234';
SELECT #firstone / #secondone AS resultthing
SELECT #firstone /CAST(#secondone AS DECIMAL (9,2))
You could use a common table expression to get the counts and then select the desired results in one swell foop:
with Counts as (
select
( select Count(*) from Sys.Tables ) as NumberOfTables,
( select Count(*) from Sys.Columns ) as NumberOfColumns
)
select NumberOfTables, NumberOfColumns,
NumberOfColumns / NumberOfTables as ColumnsPerTable,
( 100 * NumberOfColumns ) / NumberOfTables as IntegerPercentColumnsPerTable,
( 100.0 * NumberOfColumns ) / NumberOfTables as NumericPercentColumnsPerTable
from Counts;
I used existing tables since you chose not to supply DDL and sample data. So it goes.

merge CTE query in Oracle

I am looking for an optimized way to merge CTE query as mentioned below. In the below query, the same table is getting hit twice, I am looking for an option to hit this table once and it will only be possible if I remove CTE and put everything into single query. I am using CTE as I need to derive column value and then compare that value..
Query
with cte as
(
select distinct
'UP' search_update_code,
'G' search_prov_entity_type,
prpr.prpr_id search_prov_id,
prpr.mctn_id search_tax_id,
'UP' group_provdata_upd_cd,
'G' group_provdata_entity,
case
when enroll_type = 'AH' THEN 'A'
when enroll_type = 'VP' THEN 'A'
when enroll_type = 'CK' THEN ' '
end group_provdata_clm_eft_pay_ind <-- deriving values here
from
fsg_prcb_pe_enroll_stream prcb
inner join
cmc_prpr_prov prpr on prpr.mctn_id = prcb.prov_tin_number <-- 1st hit
where
prpr.prpr_entity ='G'
and prcb.prov_tin_number = ?
and prcb.error_flag is null
)
select distinct
cte.*
from cte
inner join cmc_prpr_prov prpr on cte.search_prov_id = prpr.prpr_id <-- 2nd hit
where cte.group_provdata_clm_eft_pay_ind <> prpr.prpr_cl_eft_ind <--- comparing derived values here
and prpr_term_dt >= systimestamp
You can rewrite your query like below:
with cte as
(
select distinct
'UP' search_update_code,
'G' search_prov_entity_type,
prpr.prpr_id search_prov_id,
prpr.mctn_id search_tax_id,
'UP' group_provdata_upd_cd,
'G' group_provdata_entity,
case
when enroll_type = 'AH' THEN 'A'
when enroll_type = 'VP' THEN 'A'
when enroll_type = 'CK' THEN ' '
end group_provdata_clm_eft_pay_ind, <-- deriving values here
prpr.prpr_cl_eft_ind prpr_cl_eft_ind_2,
prpr_term_dt
from
fsg_prcb_pe_enroll_stream prcb
inner join
cmc_prpr_prov prpr on prpr.mctn_id = prcb.prov_tin_number <-- 1st hit
where
prpr.prpr_entity ='G'
and prcb.prov_tin_number = ?
and prcb.error_flag is null
)
select distinct
cte.*
from cte
where group_provdata_clm_eft_pay_ind <> prpr_cl_eft_ind_2 <--- comparing derived values here
and prpr_term_dt >= systimestamp

Select the first row that meets a condition + 1 row above

I have written a SQL query to return the following results:
Rows returned
However, I need to further 'filter' it down to only the rows highlighted in yellow, because I want the first row that has param_id = 'update_flag' AND param_val = '1'. I also need the row above that, because I need to retrieve the param_val value (202017) that corresponds to param_id = 'period_from' for the same Order Number (156 in this example).
This is my code, I'm getting data from 2 different tables:
SELECT
report1.orderno AS t1_orderno,
report2.orderno AS t2_orderno,
report1.report_name AS t1_reportname,
report2.report_name AS t2_reportname,
report1.variant,
report1.status,
report1.client,
report2.param_id,
report2.param_val
FROM report1
INNER JOIN
report2
ON report1.orderno = report2.orderno
AND report2.param_id IN
(
'period_from',
'update_flag'
)
AND report1.report_name = 'PR28'
AND report1.variant = '20'
AND report1.status = 'T'
AND report1.client = '10'
ORDER BY
report1.orderno DESC
Thanks for any help in advance, it's doing my head in!
WITH num_row AS (
SELECT row_number() OVER (ORDER BY report1.orderno DESC) as nom,
report1.orderno AS t1_orderno,
report2.orderno AS t2_orderno,
report1.report_name AS t1_reportname,
report2.report_name AS t2_reportname,
report1.variant,
report1.status,
report1.client,
report2.param_id,
report2.param_val
FROM report1
INNER JOIN
report2
ON report1.orderno = report2.orderno
AND report2.param_id IN (
'period_from',
'update_flag'
)
AND report1.report_name = 'PR28'
AND report1.variant = '20'
AND report1.status = 'T'
AND report1.client = '10'
)
SELECT * FROM num_row
WHERE nom BETWEEN 1 AND 2

Need help on how to convert this select to a DELETE statement:

I need help as to how to convert this select to a delete statement.
SELECT stud_term_sum_div.id_num,
stud_term_sum_div.hrs_enrolled,
stud_term_sum_div.transaction_sts,
student_crs_hist.crs_cde,
student_crs_hist.transaction_sts
FROM stud_term_sum_div,
student_crs_hist
WHERE ( stud_term_sum_div.yr_cde = student_crs_hist.yr_cde ) and
( stud_term_sum_div.trm_cde = student_crs_hist.trm_cde ) and
( stud_term_sum_div.id_num = student_crs_hist.id_num ) and
( ( stud_term_sum_div.yr_cde = '2013' ) AND
( stud_term_sum_div.trm_cde = 'FA' ) AND
( stud_term_sum_div.hrs_enrolled >= 3.00 ) AND
( student_crs_hist.transaction_sts = 'D' ) )
The most straight-forward conversion is below:
DELETE * FROM stud_term_sum_div
WHERE ( stud_term_sum_div.yr_cde = student_crs_hist.yr_cde ) and
( stud_term_sum_div.trm_cde = student_crs_hist.trm_cde ) and
( stud_term_sum_div.id_num = student_crs_hist.id_num ) and
( ( stud_term_sum_div.yr_cde = '2013' ) AND
( stud_term_sum_div.trm_cde = 'FA' ) AND
( stud_term_sum_div.hrs_enrolled >= 3.00 ) AND
( student_crs_hist.transaction_sts = 'D' ) )
BUT, before you go executing that, please check that the WHERE clause really contains the conditions to be used for deletion. Note that this SQL statement will delete the entire row (a/k/a record) when the attributes in the WHERE clause satisfy the stated conditions.
If you only want to remove the data from the attributes (as opposed to the entire record), you'd need to use an SQL UPDATE statement instead. The (simplified) syntax for that is as follows:
UPDATE <table_name>
SET <attribute1> = <value1>
[, SET <attribute_n> = <value_n>...]
WHERE <conditions on which the record should be updated>
Doing a search on Bing, google, <insert your favorite search engine here> for "SQL DELETE" or "SQL UPDATE" should get you all the information you need (e.g. MSDN, for one).

SQL Query takes to long to return data

Looking for a better way to write this query and my SQL skills aren't great, basic really so looking for any pointers to make this better. This is only the first two columns and the full report will have a further 10.
I'm taking a specific set of repair types and doing analysis on them with counts and calculations. The 1st is jobs brought forward to the current financial year and the second is total amount of jobs currently received.
SELECT
"Type",
(
SELECT
NVL (COUNT(jjo.jjobno), 0)
FROM
jjobh jjo
WHERE
jjo.jclcode = 'L'
AND jjo.jstatus <> '6'
AND jjo.year_rec <> (
SELECT
sub_code
FROM
code_table
WHERE
main_code = 'YEAR'
)
AND (
week_comp IS NULL
OR year_comp = (
SELECT
sub_code
FROM
code_table
WHERE
main_code = 'YEAR'
)
)
AND jjo.jrepair_type = "Type"
) AS "B/F",
(
SELECT
NVL (COUNT(jjo.jjobno), 0)
FROM
jjobh jjo
WHERE
jjo.jclcode = 'L'
AND jjo.jstatus <> '6'
AND jjo.year_rec = (
SELECT
sub_code
FROM
code_table
WHERE
main_code = 'YEAR'
)
AND jjo.jrepair_type = "Type"
) AS "Recvd"
FROM
(
SELECT
rep.repair_type_code AS "Type"
FROM
repair_type rep
WHERE
rep.client = 'L'
AND rep.work_centre = '004682'
ORDER BY
rep.repair_type_code
)
ORDER BY
"Type";
Your code is a mess. I suspect you want something like:
SELECT jjo.jrepair_type, count(*) as valbf
FROM (SELECT coalesce(COUNT(jjo.jjobno), 0)
FROM jjobh jjo cross join
(SELECT sub_code
FROM code_table
WHERE main_code = 'YEAR'
) sc
WHERE jjo.jclcode = 'L' AND
jjo.jstatus <> '6' AND
jjo.year_rec <> sc.sub_code AND
(week_comp IS NULL OR
year_comp = sc.sub_code
)
) jjo join
(SELECT rep.repair_type_code AS "Type"
FROM repair_type rep
WHERE rep.client = 'L' AND
rep.work_centre = '004682'
) rtc
on jjo.jrepair_type = rtc.repair_type_code
group by jjo.jrepair_type;
It looks like you want to join the "jjo" table to the "repair type code" table, producing information about each repair type. The order by in the subquery is useless.
My suggestion is to move the "jjo" table to the outer "from". You should also move the WHERE clauses to the outermost WHERE clause (which I didn't do). I haven't quite figured out the date logic, but this might get you on the right track.