MySQL Query GroupingSubQuery Question - sql

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

Related

SQL - Group by the base of an ID

My SQL is not really good, but I am improving.
I try to extract records from a table with sales data. I want to know how much profit was made by a retailer and its subsidiaries per month.
The retailer_id is build from the root of 5 digits and (if subsidiaries exist) an adjacent _ with two digits. Like so:
without subsidiaries: 30000
with subsidiaries: 30000_01, 30000_02
Code:
SELECT
retailer_id,
MONTH(Date(created_at)) AS month,
SUM(grand_total) AS Totals
FROM
sales_table
GROUP BY
retailer_id, month
As you can imagine, the retailer with subsidiaries are still separated line items.
As requested, I will give an example:
raw data
retailer_id
month
grand total
10006
12
10
10006
9
20
10006
9
40
10006_10
12
40
10015
9
10
10015
11
10
10015
12
5
10015
11
20
expected result:
retailer_id
month
Totals
10006
12
50
10006
9
60
10015
9
10
10015
11
30
10015
12
5
10015
11
20
Thank you for your help!
The answer is 'left'. As in this one:
select
left(retailer_id, 5),
Month(Date(created_at)) AS month,
sum(grand_total) AS Umsatz
FROM sales_order
WHERE store_id = '2' AND NOT status = 'canceled' AND created_at between '2021-09-01' AND '2022-01-27'
GROUP BY left(retailer_id, 5), month
ORDER BY left(retailer_id,5);

How to query data and its count in multiple range at same time

I have a table like below,
id
number
date
1
23
2020-01-01
2
12
2020-03-02
3
23
2020-09-02
4
11
2019-03-04
5
12
2019-03-23
6
23
2019-04-12
I want to know is that how many times each number appears per year, such as,
number
2019
2020
23
1
2
12
1
1
11
1
0
I'm kinda stuck.. tried with left join or just a single select, but still, cannot figure out how to make it, please help thank you!
SELECT C.NUMBER,
SUM
(
CASE
WHEN C.DATE BETWEEN '20190101'AND '20191231'
THEN 1 ELSE NULL
END
) AS A_2019,
SUM
(
CASE
WHEN C.DATE BETWEEN '20200101'AND '20201231'
THEN 1 ELSE NULL
END
) AS A_2020
FROM I_have_a_table_like_below AS C
GROUP BY C.NUMBER

Get YTD sum value

The first two columns work great but I do not know how to get the results for the third column. Please tell me how I can have the third column to show the year to date data with accordance to the week. Please provide assistance.
select "Builder","Traffic", sum(cast("Traffic" as int)) as YTD
from trafficdatapcr
where "Week" = '2016-12-11'
group by "Builder","Traffic"
The sample data:
Week Builder Traffic
2016-12-11 Macys 100
2016-10-11 Bloomingdales 15
2016-08-11 Saks 85
2016-02-11 Cole Haan 95
2015-12-25 Kroger 65
My current results:
Builder Traffic YTD
Macys 100 100
The expected results:
Builder Traffic YTD
Macys 100 100
Saks 0 85
Bloomingdales 0 15
Cole Haan 0 95
Kroger 0 65
Your where clause is eliminating the the records you desire, use a case to conditionally display the traffic for the desired week instead of the where clause
select "Builder"
, case when "Week" = to_date('2016-12-11',YYYY-MM-DD') then "Traffic" else 0 end as "Traffic"
, sum(cast("Traffic" as int)) as YTD
from trafficdatapcr
group by "Builder","Traffic"
Order by week Desc
It does seem odd though that if someone were to select 2016-10-11 the YTD would be all dates.... so perhaps you want to conditionally sum as well...
select "Builder"
, case when "Week" = to_date('2016-12-11','YYYY-MM-DD') then "Traffic" else 0 end as "Traffic"
, sum(case when "week"<=to_date('2016-12-11','YYYY-MM-DD') then cast("Traffic" as int) else 0 end) as YTD
from trafficdatapcr
group by "Builder","Traffic"
Order by week Desc
This way
Macys will show as 0 0
Bloomingdales would be 15 15
So 2nd query should return (assumign date of 2016-10-11) but in correct date order (don't know what order you want)
Builder Traffic YTD
Macys 0 0
Saks 0 85
Bloomingdales 15 15
Cole Haan 0 95
Kroger 0 65

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;

Adding values that don't exist in SELECT statement output

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.