Adding values that don't exist in SELECT statement output - sql

I am not sure how to ask this, due to my lack of experience, so please bear with me.
I am using a SELECT statement to extract pending applications (i.e. no completed date) and counting their totals (plus some other counting). There are certain project types that I need to gather from, 8 of them, where only 4 of them currently have a pending application. I still need to show the other project types with a 0 in the count column. If I try to union with a query that will pull all data, pending or not, I get duplicate rows (minus the count columns) for the 4 project types with currently pending applications. If I left join to the project type table, I get a null row. Neither are what I want. Does anyone have any suggestions?
Output of the union:
General Construction 0 0 90 0
General Coverage 0 0 90 0
General Coverage 1 740 90 90
General Renewal 0 0 90 0
Individual Construction 0 0 90 0
Individual Coverage 0 0 180 0
Individual Renewal 0 0 90 0
Individual Renewal 2 1027 90 180
Approval 0 0 90 0
Approval 22 565 90 1980
Other - Renewal 0 0 90 0
Other - Renewal 21 1119 90 1890
Output without the necessary '0' rows:
General Coverage 1 740 90 90
Individual Renewal 2 1027 90 180
Other - Renewal 21 1119 90 1890
Approval 22 566 90 1980
Output that I would like to see is:
General Construction 0 0 90 0
General Coverage 1 740 90 90
General Renewal 0 0 90 0
Individual Construction 0 0 90 0
Individual Coverage 0 0 180 0
Individual Renewal 2 1027 90 180
Approval 22 565 90 1980
Other - Renewal 21 1119 90 1890
Please let me know what else I can provide to help you help me.

You don't provide names of your columns or anything like that.
What you need is a driver table with all valid values. You can then use left outer join to get the result set you want:
select driver.val, coalesce(q.col2, 0), coalesce(q.col3, 0), coalesce(q.col4, 0)
from (select 'General Construction' as val from dual union all
select 'General Coverage' as val from dual union all
select 'General Renewal' as val from dual union all
select 'Individual Construction' as val from dual union all
select 'Individual Coverage' as val from dual union all
select 'Individual Renewal' as val from dual union all
select 'Approval' as val from dual union all
select 'Other - Renewal' as val from dual
) driver left outer join
(query without 0 rows) q
on driver.val = q.col1
If NULLs are okay instead of 0s, then the coalesce() is not needed.

Related

Query to solve a rolling issue

I am seeking guidance on how to solve the following issue?
My data look like:
id
Total
Allowed
Left
1
815
150
655
2
815
15
650
3
815
135
515
4
815
1380
-864
5
815
109
-974
6
815
10
-984
"Left" column is derived from difference of Total and Allowed and then it rolls to next row with Left - Allowed to set value of Left in next rows.
I want to create a new column of Final where if Left value is greater than Allowed, then set the value of Final as Allowed; however, where Left value is less than Allowed, set the value Final for all such rows to 0 except for first row where Left value was less than 0 and set it to the value of last positive Left value. Output should be like this:
id
Total
Allowed
Left
Final
1
815
150
655
150
2
815
15
650
15
3
815
135
515
135
4
815
1380
-864
515
5
815
109
-974
0
6
815
10
-984
0
The way I tried to do is:
Update table
set Final =
Case when Left >= Allowed then Left End
However, i do not understand how to do the remaining part. I am new to this site and let me know if more details are required to help provide solution to me.
You can use an updatable CTE
WITH t AS (
SELECT *,
f = CASE WHEN [Left] > Allowed THEN Allowed
WHEN [Left] > 0 THEN [Left]
WHEN LAG([Left]) OVER (ORDER BY id) > 0 THEN LAG([Left]) OVER (ORDER BY id)
ELSE 0 END
FROM YourTable
)
UPDATE t
SET Final = f;
db<>fiddle

Calculate fixed Cost/day for multiple services on same date

Desired Output table T with Calculated Cost column:
SvcID Code ID Date Mins Units Cost
1 3000 15 4/4/2016 60 10 70
2 3000 17 4/4/2016 45 10 0
3 3000 15 5/2/2016 30 10 70
4 3000 18 5/2/2016 60 10 0
5 3000 10 5/2/2016 30 10 0
6 4200 16 2/1/2016 60 4 60
7 4200 9 2/1/2016 30 2 30
Query for calculating and displaying:
SELECT
...
,CASE
WHEN Code=4200 THEN Units*15
WHEN Code=3000 THEN ?
END AS Cost
FROM ...
WHERE Code IN ('3000','4200')
GROUP BY ....;
Cost should be a total of 70 for all services offered on same date for Code 3000, irrespective of number of services offered. No relation between Minutes and Units for this Code for calculating Cost.
One way could be to calculate cost as 70 for any one service and make the remaining services cost 0 for same date. Can this be done in the CASE statement?
Any better way to achieve this?
You need to Investigate Window functions MSDN.
Your case would become something like this:
-- New select statament
SELECT
...
,CASE
WHEN Code=4200 THEN Units*15
WHEN Code=3000 THEN ( CASE WHEN DuplicateNum = 1 THEN 70 ELSE 0 END )?
END AS Cost
FROM(
-- Your current query (with case statement removed) and ROW_NUMBER() function added
SELECT
..., ROW_NUMBER() OVER( PARTITION BY Code, Date ORDER BY ID ) AS DuplicateNum
FROM ...
WHERE Code IN ('3000','4200')
GROUP BY ....
) AS YourCurrentQuery;

Issue with Oracle select query 2

I have a table report of production, and I want to bridge between minus value and positive value on QTY field.
I want to make a new column with positive value, and another column with negative value selected from the QTY field.
mtl_trx qty uom
1 20 1230 KG
2 39 950 KG
3 45 100 LBR
4 91 250 KG
5 118 -500 KG
6 125 -284 KG
7 137 -120 KG
8 143 -80 KG
If I understand correctly, you want to select two columns, one showing the positiv values, one the negative ones? Use a case construct to decide whether to show a value or not.
select mtl_trx, qty, uom,
case when qty > 0 then qty end as qty_pos,
case when qty < 0 then qty end as qty_neg
from mytable;
select mtl_trx, qty, uom,
case when qty > 0 then qty else 0 end as positive,
case when qty < 0 then qty else 0 end as negative
from production;

Oracle SQL Query one row with monthly value only, but need to group it by month

I can't figure out the correct query on Oracle SQL
I have the following data:
Name Monthly_amount Start_date
Bob 100 April 2014
Mike 120 June 2014
Steve 80 Sept 2014
Bob 50 Dec 2014
And I would like to get the following result
Name |Jan-14| Feb-14| Mar-14| Apr-14 |May-14| Jun-14| Jul-14 |Aug-14|Sep-14|Oct-14| Nov-14| Dec-14
Bob 0 0 0 100 100 100 100 100 100 100 100 150
Mike 0 0 0 0 0 120 120 120 120 120 120 120
Steve 0 0 0 0 0 0 0 0 80 80 80 80
Something along the lines of this should work for you. If you need the column definitions to be dynamic, you would have to create it dynamically, but it's better to do that kind of things in your application.
SELECT Name,
SUM(CASE WHEN Start_date <= TO_DATE('01-JAN-2014','DD-MON-YYYY')
THEN Monthly_Amount ELSE 0 END) AS Jan14,
SUM(CASE WHEN Start_date <= TO_DATE('01-FEB-2014','DD-MON-YYYY')
THEN Monthly_Amount ELSE 0 END) AS Feb14,
(etc.)
FROM table1
GROUP BY Name;
(This assumes Name uniquely defines a person)

MySQL Query GroupingSubQuery Question

I am having trouble getting my head around this query for some reason and I was wondering if someone would be able to help me out here. I have the following 3 tables:
opp_cstm:
id_c make_c time_followup_c lead_category_c lead_type_c
9 GMC 224 GM Internet Sales
e Buick 809 GM Internet Service
8 GMC 1559 Dealer Web Sales
2 Cadillac 10596 Dealer Web Service
3 Chevrolet 15595 GM Internet Sales
4 Chevrolet 905 GM Internet Service
opportunities:
id date_entered deleted
2 2010-07-16 16:46:21 0
3 2010-07-16 16:55:53 0
4 2010-07-16 19:30:12 0
8 2010-07-16 16:44:13 0
9 2010-07-16 16:39:17 0
e 2010-07-16 16:41:44 0
leads_objectives:
makes_carried resp_time_obj
GMC 18000
Ford 7200
Cobalt 43200
Chevrolet 18000
Buick 18000
Cadillac 7200
I am needing to get the following layout (this will obviously be grouped by date, LCat):
Date LCat LType #ofLds AvgResp #LdsRespOT %LdsRespOT #Lds!RespOT %Lds!RespOT
19-Jul GM Internet Sales 10 18 minutes 7 70% 3 30%
19-Jul GM Internet Service 20 20 minutes 10 50% 10 50%
19-Jul Handraiser Sales 10 45 minutes 5 50% 5 50%
20-Jul Dealer Web Sales 20 120 minutes 5 25% 15 75%
20-Jul Dealer Web Service 10 7 minutes 3 30% 7 70%
Explanation of each column I need:
Date: opportunities.date_entered = today (this needs to be on everything of course)
LCat: opp_cstm.lead_category
LType: opp_cstm.lead_type
#ofLds: this needs to be the Count of opportunities where deleted = "0" and Lead Category is not null
AvgResp: Avg. of timefollowup-C field in opportunities where Deleted = "0" and Lead Category is not null and and time_followup_c > 0 and not null
#LdsRespOT: Count of opportunities where Deleted = "0" AND Lead Category is not null AND time_followup_c is less than or equal to resp_time_obj AND make_c = makes_carried and time_followup_c > 0 and not null
%LdsRespOT: (#LdsRespOT / #ofLds)
#Lds!RespOT: (#ofLds - #LdsRespOT)
%Lds!RespOT: (#Lds!RespOT / #ofLds)
I am having a hard time getting my head around this query. I was wondering if someone on here could provide some assistance of some sort with this one? How would I write this query correctly?
I have tried several times but fail every time and I am getting frustrated! I know I am just missing some grouping of some kind or some kind of sql subquery that I am missing.
Any help would be greatly appreciated!
Thanks!
For anyone who comes across this that might need help with something like this, here is what I ended up doing:
SELECT
opportunities.date_entered as Date,
opportunities_cstm.lead_category_c as LCat,
opportunities_cstm.lead_type_c as LType,
count(opportunities.id) as '# of Lds',
SUM(opportunities_cstm.time_followup_c)/count(opportunities.id) as AvgResp,
SUM(
CASE
WHEN (
opportunities_cstm.time_followup_c IS NOT NULL
AND
opportunities_cstm.time_followup_c < leads_handling_objectives.resp_time_obj
)
THEN
1
ELSE
0
END
) as '#LdsRespOT',
(SUM(
CASE
WHEN (
opportunities_cstm.time_followup_c IS NOT NULL
AND
opportunities_cstm.time_followup_c < leads_handling_objectives.resp_time_obj
)
THEN
1
ELSE
0
END
) /count(opportunities.id))*100 as '%LdsRespOT',
count(opportunities.id) - SUM(
CASE
WHEN (
opportunities_cstm.time_followup_c IS NOT NULL
AND
opportunities_cstm.time_followup_c < leads_handling_objectives.resp_time_obj
)
THEN
1
ELSE
0
END
)as '#Lds!RespOT',
((count(opportunities.id) - SUM(
CASE
WHEN (
opportunities_cstm.time_followup_c IS NOT NULL
AND
opportunities_cstm.time_followup_c < leads_handling_objectives.resp_time_obj
)
THEN
1
ELSE
0
END
))/count(opportunities.id))*100 as '%Lds!RespOT'
FROM
opportunities
INNER JOIN
opportunities_cstm
ON
opportunities_cstm.id_c = opportunities.id
AND
opportunities_cstm.lead_category_c IS NOT NULL
AND
opportunities_cstm.lead_category_c NOT LIKE ''
INNER JOIN
leads_handling_objectives
ON
leads_handling_objectives.makes_carried = opportunities_cstm.make_c
WHERE
opportunities.date_entered = DATE(NOW())
AND
opportunities.deleted='0'
GROUP BY
opportunities_cstm.lead_category_c