joining no of reports in oracle - sql

Hi I want to generate the report which will contain following things:
Daily report by country/destination against counts.
Eg.
No of contributions
No videos
No of experiences
Based on count yesterday, total for week, total for year for each destination.
I have written following query to count total for week.
select a.name, count(e.id),count(uc.id),count(v.id)
from accommodation a, user_contribution uc,experience_video ev, video v,
(select id "ID",user_contribution_id,accommodation_id,case
when modified_on is null then trunc(created_on)
else trunc(modified_on) end last_modified from experience)e
where
e.last_modified between trunc(sysdate)-7 and trunc(sysdate) and
e.accommodation_id = a.id and
e.user_contribution_id = uc.id and
e.id = ev.experience_id and
v.id = ev.video_id
group by a.name
union
select l.name, count(ex.id),count(uc.id),count(v.id),count(r.id)
from location l, user_contribution uc,experience_video ev, video v,
(select id "ID",user_contribution_id,location_id,case
when modified_on is null then trunc(created_on)
else trunc(modified_on) end last_modified from experience)ex
where
ex.last_modified between trunc(sysdate)-7 and
trunc(sysdate) and
l.id = ex.location_id and
ex.user_contribution_id = uc.id and
ex.id = ev.experience_id and
v.id = ev.video_id
group by l.name;
I can similarly write the query to extract weekly and yearly count.
basically I want all counts in one row for each destination.
Is there any better way of writing this query?
Would appreciate your help.

Related

how to write an average of an average query in SQL

I am performing the below query. I need to get the average of (avg_per_deal). Each email can have multiple deals, and each deal can have many averages. I want to get the query to average ALL the averages of the different deals, in order to have one aggregate average per email. I'm not sure how to write another subquery to do that with what I currently have:
WITH purs AS (
SELECT
u.email,
di.internal_name,
dh.id,
dh.created_at,
dh.deal_id,
dh.new_demand_status
FROM
deal.deal_history dh
JOIN deal.deal d ON d.id = dh.deal_id
JOIN deal.deal_intent di ON di.id = d.supply_intent
JOIN axd.user u ON u.public_id = di.user_public_id
WHERE
dh.stat = 'purs'
AND dh.ostat = 'teas'
AND di.type != 'wav'
),
signda AS (
SELECT
dh.id,
dh.created_at,
dh.deal_id,
dh.stat
FROM
deal.deal_history dh
JOIN deal.deal d ON d.id = dh.deal_id
JOIN deal.deal_intent di ON di.id = d.supply_intent_id
WHERE
stat = 'signda'
AND di.type != 'wav'
)
SELECT
p.email,
p.internal_name,
AVG(age(sn.created_at,p.created_at)) AS avg_per_deal
FROM
pur p
JOIN signda sn ON sn.deal_id = p.deal_id
WHERE p.created_at > now() - interval '1 month'
GROUP BY 1,2;
This gives me the average for the different deals for each email. I need the average of the different averages (per unique email).
You can enclose the main select as a subquery and then compute the average there.
For example, you can change the main select from:
select p.email, p.internal_name,
avg(age(sn.created_at,p.created_at)) as avg_per_deal
from pur p
join signda sn on sn.deal_id = p.deal_id
where p.created_at > now() - interval '1 month'
group by 1,2
to:
select email, avg(avg_per_deal)
from (
select p.email, p.internal_name,
avg(age(sn.created_at,p.created_at)) as avg_per_deal
from pur p
join signda sn on sn.deal_id = p.deal_id
where p.created_at > now() - interval '1 month'
group by 1,2
) x
group by email

How to use 1 SQL query related to date and time in order to compare value difference

SELECT c.treatment_category, a.treatment_id, MAX(a.counts - b.counts) AS ReviewDifference
FROM
(SELECT treatment_id, COUNT(treatment_id) AS counts
FROM review
WHERE DATE(review.created) BETWEEN DATE(TIMESTAMP'2016-01-01 00:00:00.0') AND DATE(TIMESTAMP'2016-12-31 23:59:59.999')
GROUP BY treatment_id) a
LEFT JOIN
(SELECT treatment_id, COUNT(treatment_id)
FROM review
WHERE DATE(review.created) BETWEEN DATE(TIMESTAMP'2015-01-01 00:00:00.0') AND DATE(TIMESTAMP'2015-12-31 23:59:59.999')
GROUP BY treatment_id) b
ON a = b
LEFT JOIN
(SELECT t.treatment_category AS category, r.treatment_id AS number
FROM treatment t
LEFT JOIN review r
ON t.treatment_id = r.treatment_id
GROUP BY category, number) c
ON b.treatment_id = c.number
GROUP BY a.treatment_id, c.treatment_category
ORDER BY ReviewDifference DESC
LIMIT 1;
I need some hints or simpler query on how to do this question since it is related to date and time. Thank you.
What treatment category has seen the biggest increase in reviews from 2015 to 2016?
Please see below for the tables.
I have provided my code snippet and I would like to find a simpler and cleaner way on writing the code.
SELECT t.treatment_id, t.treatment_name,
COUNT( CASE WHEN YEAR(created) = 2016 THEN r.review_id END)
- COUNT( CASE WHEN YEAR(created) = 2015 THEN r.review_id END) as review_count
FROM treatments t
JOIN reviews r
ON t.treatment_id = r.treatment_id
GROUP BY t.treatment_id, t.treatment_name,
ORDER BY review_count DESC

Trying to count number of complaint, cause, corrections

I am trying to create a query with the following fields, that counts the number of Complaints, causes, and corrections show up in the data.
My current error: Select non-aggregate values must be part of the associated group.
I am very new to SQL queries, and am not sure what else I'm missing. All I've done is merged to queries, and seem to be missing something.
select L.Case_ID,
L.Case_Line_ID,
A.Dealer_ID,
M.DealerCode,
H.DealerName,
substr(L.Estimate_Created_At,1,7) as CaseMonth,
count(distinct L.Complaint) as Complaint,
count(distinct C.Cause) as Cause,
count(distinct C.Correction) as Correction
from Decisiv_Tables_Prod.Stg_Decisiv_LineItems L
join Decisiv_Tables_Prod.Stg_Decisiv_Cases A on L.Case_ID = A.Case_ID
join Decisiv_Tables_Prod.Rpt_DecisivDealerMap M on A.Dealer_ID = M.DecisivDealerID
and cast(substr(L.Estimate_Created_At,1,10) as date format 'YYYY-MM-DD') between M.EffectiveStartDate and coalesce(M.EffectiveEndDate, cast('2099-12-31' as date format 'YYYY-MM-DD'))
join Decisiv_Tables_Prod.Rpt_DealerDirectoryHierarchy H on M.DealerCode = H.DealerCode
join Decisiv_Tables_Prod.Stg_Decisiv_LineItems_Clobs C on C.Case_ID = L.Case_ID
and C.Case_Line_ID = L.Case_Line_ID
group by 1,2,3,4,5
Looking to get a table with the following data example:
Dealer ID, Dealer Code, Dealer Name, Case Month, Count of Case_ID, Count of Case_Line_ID, Count of Complaint, Count of Cause, Count of Correction
You have six unaggregated columns:
select L.Case_ID,
L.Case_Line_ID,
A.Dealer_ID,
M.DealerCode,
H.DealerName,
substr(L.Estimate_Created_At,1,7) as CaseMonth,
These should all be in the group by:
group by L.Case_ID, L.Case_Line_ID, A.Dealer_ID,
M.DealerCode, H.DealerName,
substr(L.Estimate_Created_At,1,7) as CaseMonth
As Gordon wrote, the GROUP BY list doesn't match your Select, you need to either remove both Case_ID & Case_Line_ID or aggregate them:
SELECT
A.Dealer_ID,
M.DealerCode,
H.DealerName,
Substr(L.Estimate_Created_At,1,7) AS CaseMonth,
Count(L.Case_ID), -- distinct ?
Count(L.Case_Line_ID), -- distinct ?
Count(DISTINCT L.Complaint) AS Complaint,
Count(DISTINCT C.Cause) AS Cause,
Count(DISTINCT C.Correction) AS Correction
FROM Decisiv_Tables_Prod.Stg_Decisiv_LineItems AS L
JOIN Decisiv_Tables_Prod.Stg_Decisiv_Cases AS A
ON L.Case_ID = A.Case_ID
JOIN Decisiv_Tables_Prod.Rpt_DecisivDealerMap AS M
ON A.Dealer_ID = M.DecisivDealerID
AND Cast(Substr(L.Estimate_Created_At,1,10) AS DATE FORMAT 'YYYY-MM-DD') BETWEEN M.EffectiveStartDate AND Coalesce(M.EffectiveEndDate, DATE '2099-12-31')
JOIN Decisiv_Tables_Prod.Rpt_DealerDirectoryHierarchy AS H
ON M.DealerCode = H.DealerCode
JOIN Decisiv_Tables_Prod.Stg_Decisiv_LineItems_Clobs AS C
ON C.Case_ID = L.Case_ID
AND C.Case_Line_ID = L.Case_Line_ID
GROUP BY
A.Dealer_ID,
M.DealerCode,
H.DealerName,
CaseMonth
I simplified cast('2099-12-31' as date format 'YYYY-MM-DD') to DATE '2099-12-31' and used the column names/aliases in Group By (recommended over 1,2,3,4 in production code).
As Distinct is quite expensive check if you actually need to add it to those counts.

DATEDIFF in Group by causing error

I am posting it a new question as previous question has changed a bit. I am using this query:
SELECT DATEDIFF(SECOND,servicestart,CheckinTime) abondendedTime FROM Location L INNER JOIN
Interaction I
ON L.Id = I.IdLocation
WHERE ServiceEnd = '00:00:00.000'
GROUP BY L.Id, L.Description,DATEDIFF(SECOND,servicestart,CheckinTime)
and it is returning 700 rows where as I don't need this part
DATEDIFF(SECOND,servicestart,CheckinTime) in GROUP BY but If I don't put it in GROUP BY, I get error:
Column 'Interaction.ServiceStart' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I want this result set
http://prntscr.com/f993xe
I need to do these calculations.
http://prntscr.com/f995dk
I have done this part
SELECT L.Id,
L.Description AS 'Location',
COUNT(L.Id) Interactions,
SUM(CASE WHEN I.ServiceEnd = '00:00:00.000' THEN 1 ELSE 0 END) Abandoned,
(SUM(CASE WHEN I.ServiceEnd = '00:00:00.000' THEN 1 ELSE 0 END) *100)/COUNT(I.Id) AbandonedPercent
FROM Location L
INNER JOIN Interaction I
ON L.Id = I.IdLocation
GROUP BY L.Id,L.Description
and need to calculate
Average Abandon Time,Members,Repeat Members,Repeat Visits,Repeat/Interaction,Average Wait,Average Service
Above first query is for Average Abandon Time
I think this is what you want:
SELECT L.Id, L.Description,
SUM(DATEDIFF(SECOND, servicestart, CheckinTime)) as abondendedTime
FROM Location L INNER JOIN
Interaction I
ON L.Id = I.IdLocation
WHERE ServiceEnd = '00:00:00.000'
GROUP BY L.Id, L.Description;
Unlike your previous question, the column in the WHERE is different from the column used for the DATEDIFF().

I want SQLplus count(*) to return zero-values

I'm using Oracle 10.2 and have the following query:
select h.company, count(*)
from history h
where h.status = '2'
and h.substatus = '0'
and h.timestamp > '2012-01-01'
and h.timestamp < '2012-02-01'
group by h.company
having (h.company = 'AAA')
or (h.company = 'BBB')
or (h.company = 'CCC')
order by h.company
This will count the amount of times any customer from the companies AAA, BBB or CCC has reached a specific point (status = 2).
Presume no (zero) customers from BBB did so, the result will come back with 2 rows of count(AAA and CCC).
What I want: I wish for the query to return me rows for all 3 companies, even tho the count is zero.
Sorry for the odd layout of the query. It's made to work with MS Excel as well.
Edit: Sorry.. Too little caffeine. changed "Customer" in the later half of the query to "Company".
Clarification: A customer is made unique by combining "h.company" and "h.customer" (or by using the same method in customer-table (customer c), like "c.company" and "c.customer"
Edit 2: Updated code.
select c.company, count(*)
from companyregister c
left join history h on h.company = c.company
where h.status = '2'
and h.substatus = '0'
and h.timestamp > '2012-01-01'
and h.timestamp < '2012-02-01'
group by c.company
having (c.company = 'AAA')
or (c.company = 'BBB')
or (c.company = 'CCC')
order by c.company
Both sets of code from above will yield two rows as follows:
AAA 630
CCC 3020
I would like to have BBB represented, but since they have zero rows in history, they don't show.
Make a left join on the customer table. I don't know what you have named it, but like this:
select c.company, count(h.customer)
from customer as c
left join history as h on h.customer = c.customer
...
Another alternative is to use a condition when counting. I'm not sure if there is any other condition that you need along with the status, but something liket this:
select company, sum(case status when '2' then 1 else 0 end)
from history
where substatus = '0'
and timestamp > '2012-01-01'
and timestamp < '2012-02-01'
and customer in ('AAA', 'BBB', 'CCC')
group by customer
order by customer