Count Between three tables - sql

I have three tables
Data
Service
Status
Data table
Serno | ServiceId | Status | Datetime
1 2 4 12/12/2014
2 1 3 08/12/2014
Service
ServiceId | Service Name
1 Deployment
2 Designing
Status
StatusId | Status
1 Done
2 Pending
3 20%done
4 Canceled
I want a Sql code for Count (that is the status count with respect to Services)
Designing 0 0 0 1
Deployment 0 0 1 0
I have tried this
SELECT COUNT(Service.Status) AS Expr1, Service.ServiceName, Status.Status
FROM Data INNER JOIN
Service ON Hcc_Service_Data.Hcc_Service_Category_Id = Service .ServiceId INNER JOIN
Status ON Data.StatusId = Status.Status_Serno
GROUP BY Service.ServiceName, Status.Status

Select S.ServiceName,
(CASE WHEN D.Status=1 then '1' ELSE '0' END) as S1,
(CASE WHEN D.Status=2 then '1' ELSE '0' END) as S2,
(CASE WHEN D.Status=3 then '1' ELSE '0' END) as S3,
(CASE WHEN D.Status=4 then '1' ELSE '0' END) as S4
FROM Data D, Service S where
D.serviceId = S.serviceId;

Related

Creating a view from two tables, with case and sum on one table

I'm having some troubles trying to create a view from two tables, which includes a sum + case for the first table. I've tried multiple different joins/unions, and I can get just the XTS table to come over, or just the case count scenarios to work, but I cannot get both.
here are the tables. For Table 1, UWI is non-unique. For Table 2, UWI is Unique. new_view is what I'm hoping to achieve for my view.
TABLE 1
UWI ET
1 A
1 B
1 B
2 B
2 C
2 C
TABLE 2
UWI XTS
1 10
2 20
3 10
4 30
new_view
UWI XTS B_COUNT C_COUNT
1 10 4 3
2 20 3 4
3 10 4 5
4 30 3 2
Here's what I'm currently working with.
CREATE VIEW new_view AS
SELECT t1.UWI,
sum(case when t1.ET='B' then 1 else 0 end) as B_COUNT,
sum(case when t1.ET='C' then 1 else 0 end) as C_COUNT,
sum(case when t1.ET='D' then 1 else 0 end) as D_COUNT,
sum(case when t1.ET='E' then 1 else 0 end) as E_COUNT,
sum(case when t1.ET='F' then 1 else 0 end) as F_COUNT
FROM TABLE_1 t1
INNER JOIN (SELECT t2.UWI, t2.XTS AS TSC
from TABLE_2 t2)
on t1.UWI = t2.UWI
group by t1.UWI;
Your sample select does not match your sample data, so this is a guess but I think you just need to move the aggregation into an apply()
select t2.UWI, t2.XTS, s.*
from Table_2 t2
outer apply (
select
sum(case when t1.ET='B' then 1 else 0 end) as B_COUNT,
sum(case when t1.ET='C' then 1 else 0 end) as C_COUNT,
sum(case when t1.ET='D' then 1 else 0 end) as D_COUNT,
sum(case when t1.ET='E' then 1 else 0 end) as E_COUNT,
sum(case when t1.ET='F' then 1 else 0 end) as F_COUNT
from table_1 t1
where t1.UWI = t2.UWI
group by t1.UWI
)s

Union with Group By

Had a look at other questions, tried different things but still returning more than one row.
Problem with Union on 2 tables, with group by clause. There should only be one row returned, grouped by the serviceID.
SELECT
serviceID,
serviceName,
FullCount,
WaitingCount,
InProgressCount
from (
select
a.serviceID,
serviceName,
count(applicantID) FullCount,
ISNULL(SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END),0) AS WaitingCount,
ISNULL(SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END),0) AS InProgressCount
from Products s
left join Assigns a on a.serviceID = s.productID
WHERE s.clientID = #ClientID
group by serviceID, serviceName
UNION
select
s.serviceID,
p.serviceName,
count(s.ApplicantID) FullCount,
ISNULL(SUM(CASE WHEN s.status = 0 THEN 1 ELSE 0 END),0) AS WaitingCount,
ISNULL(SUM(CASE WHEN s.status = 1 THEN 1 ELSE 0 END),0) AS InProgressCount
from Legacies s
Left Join Products p on s.serviceID = p.productID
WHERE s.client = #CompanyName
group by serviceID, serviceName
) t
GROUP BY serviceID, serviceName
I'm always getting 2 rows returned, one from each of the tables. I need to group them both together so it only returns 1 row, based on the servicedID.
The data I'm trying to return is from the following tables..
Products Table
productID serviceName
-------------------------
1 Gold Service
2 Silver Service
3 Bronze Service
Assigns Table
ApplicantID serviceID status
-------------------------------------
1 1 0
2 1 0
3 1 1
4 2 0
5 1 1
Legacies Table
ApplicantID serviceID status
-------------------------------------
1 1 0
2 1 0
3 1 0
4 2 0
5 1 1
The result I'm trying to get is one row per serviceID, to show how many applicants are on this service in both the Legacies and Assigns table, something like:-
serviceID serviceName FullCount WaitingCount InProgressCount
----------------------------------------------------------------
1 Gold Service 8 5 3
2 Silver Service 2 2 0
3 Bronze Service 0 0 0
FullCount is a total number of applicants on each service, WaitingCount is the number of applicants on the service with a status of '0' and InProgressCount is the number on this service with a status of '1'
Based on additional information, I think you can just union all the Legacies and Assigns tables.
still untested
select serviceID, servicename, count(*) fullcount
,sum(case when status = 0 THEN 1 ELSE 0 END) AS WaitingCount
,SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS InProgressCount
from (
select ApplicantID, serviceID, status
from Assigns
WHERE clientID = #ClientID
union all
select ApplicantID, serviceID, status
from Legacies
WHERE clientID = #ClientID
) combined
left join Products P on P.productID = combined.serviceID
group by serviceID, servicename
below is before edit
It's hard to tell because you do not post enough information (no sample data, no table structures, no expected output). But I think you can probably combine it all into 1 query:
untested which should be obvious with the lack of information.
SELECT isnull(a.serviceID, L.serviceID) serviceID, p.serviceName
,count(*) FullCount, SUM(CASE WHEN isnull(a.status, L.status) = 0 THEN 1 ELSE 0 END) WaitingCount
,sum(CASE WHEN isnull(a.status, L.status) = 1 THEN 1 ELSE 0 END) InProgressCount
from Legacies L
full outer join Assigns a on a.serviceID = L.serviceID
right outer join Products P on P.productID = isnull(a.serviceID, L.serviceID)
where (P.clientID = #ClientID
or L.client = #CompanyName
)
group by isnull(a.serviceID, L.serviceID), p.serviceName

SQL Group By with multiple counts

I'm trying to group a list of services together along with the number of applicants in each service, but I also need a count on the status each applicant is in.
Applicants table
serviceID clientID applicantID status
----------------------------------------------------
1 41 1 1 (Processing)
1 41 16 1 (Processing)
1 41 15 2 (Ready)
2 41 12 1 (Processing)
2 41 18 3 (Complete)
Service table:
serviceID serviceName
--------------------------
1 Full Service
2 Part Service
Results need to look like:
serviceName totalApplicants processingCount readyCount completeCount
---------------------------------------------------------------------------
Full Service 3 2 1 0
Part Service 2 1 0 1
I've got the following, but it's returning the same count in each of the columns:-
SELECT
Services.serviceName,
(COUNT(Applicants.applicantID)) AS totalApplicants,
ISNULL(SUM(CASE WHEN Applicants.status = 1 THEN 1 ELSE 0 END), 0) AS processingCount,
ISNULL(SUM(CASE WHEN Applicants.status = 2 THEN 1 ELSE 0 END), 0) AS readyCount,
ISNULL(SUM(CASE WHEN Applicants.status = 3 THEN 1 ELSE 0 END), 0) AS completeCount
FROM
Applicants
LEFT JOIN
Services ON Applicants.serviceID = Services.serviceID
WHERE
Applicants.clientID = #CompanyID
GROUP BY
Services.serviceName
You can do conditional aggregation:
select
s.serviceName,
count(s.serviceID) totalApplicants,
sum(case when status = 1 then 1 else 0 end) processingCount,
sum(case when status = 2 then 1 else 0 end) readyCount,
sum(case when status = 3 then 1 else 0 end) completeCount
from service s
left join applicants a on a.serviceID = s.serviceID AND a.clientID = #CompanyID
group by s.serviceID, s.serviceName
The conditional expression use standard case expression; depending on the database that you are actually using, neater alternatives may exists.
Your query should be fine, but it can be simplified to:
SELECT s.serviceName,
COUNT(a.AppicantId) AS totalApplicants,
SUM(CASE WHEN a.status = 1 THEN 1 ELSE 0 END) AS processingCount,
SUM(CASE WHEN a.status = 2 THEN 1 ELSE 0 END) AS readyCount,
SUM(CASE WHEN a.status = 3 THEN 1 ELSE 0 END) AS completeCount
FROM Services s LEFT JOIN
Applicants a
ON a.serviceID = s.serviceID AND
a.clientID = #CompanyID
GROUP BY s.serviceName ;
Notes:
It looks like you want a row for every service, so that should be the first table in the LEFT JOIN.
Hence the filtering on the company goes into the ON clause.
Table aliases make the query easier to write and to read.
No ISNULL() is needed (and I prefer COALESCE() over ISNULL()).

Counting Values based on certain criteria SQL

I am trying to Write a View for some reporting in our CRM program and I'm having trouble with the counts. We are trying to count the number of referrals based on certain criteria. I feel like the way I wrote the view is incorrect. I am trying to use a CASE statement to make sure it counts the values that I want, but I the numbers I am getting I am not able to validate with reverse engineering.
Did I structure the CASE statement correctly?
(Note: I do realize that client is misspelled, unfortunately whoever wrote the database before I got it had some spelling issues.)
This is what I have written so far:
SELECT Comp_Name, Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Client' Then 1
ELSE NULL END) AS Client_Referrals,
Count(Case WHEN lead_companyprimaryreferralsource IS NOT NULL Then 1 Else Null End) AS Target_Referrals,
Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Prospect' Then 1 Else Null End) As Prospective_Client_Referral,
Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Lost_Clent' Then 1 Else Null End) AS Lost_Client_Referral,
Count(Case WHEN mcgr_companyid IS NOT NULL Then 1 Else NULL END) AS Intro_By_MCG
FROM Company
RIGHT JOIN Lead on Lead_PrimaryCompanyID = Comp_CompanyId
RIGHT JOIN MCGRelationships on mcgr_companyid = Comp_CompanyId
WHERE COMP_Name IS NOT NULL
Group By Comp_Name
Here is a Sample of What i'm getting:
Client1 0 0 0 0 1
Client2 0 0 0 0 2
Client3 0 0 0 0 1
Client4 0 0 0 0 1
Client5 0 0 0 0 2
Client6 0 0 0 0 2
Client7 0 0 4 0 4
Client8 0 0 0 0 2
Client9 0 2 2 0 2
Client10 12 6 0 0 12
Client11 0 0 0 0 2
When I just run a query on the table where Client 10 is the Primary Referral source, I get nothing. So I can't account for those 12 instances.
I think your problem may be in the join to MCGRelationships, if each company record can have more than one relationship record. If I'm following you correctly, you want Intro_By_MCG to be 1 if that record exists in MCGRelationships, regardless of the number of times it appears there. By joining the table, your query would be counting a lead once for each MCGRelationship associated with the company the lead comes from. Try this and let us know if the result is different:
SELECT Comp_Name, Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Client' Then 1
ELSE NULL END) AS Client_Referrals,
Count(Case WHEN lead_companyprimaryreferralsource IS NOT NULL Then 1 Else Null End) AS Target_Referrals,
Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Prospect' Then 1 Else Null End) As Prospective_Client_Referral,
Count(Case WHEN comp_primaryreferralsource IS NOT NULL and Comp_type = 'Lost_Clent' Then 1 Else Null End) AS Lost_Client_Referral,
Count(Case WHEN EXISTS (Select Comp_CompanyId FROM MCGRelationships WHERE mcgr_companyid = Comp_CompanyId) Then 1 Else NULL END) AS Intro_By_MCG
FROM Company
RIGHT JOIN Lead on Lead_PrimaryCompanyID = Comp_CompanyId
WHERE COMP_Name IS NOT NULL
Group By Comp_Name

Need Help on Oracle Select Query

I am finding difficulty to frame a select query.
PFB, for the table and corresponding data:
ID DLS MATCH_STATUS LAST_UPDATE_TIME BO CH FT
1 0 0 09-07-2013 00:00:00 IT TE NA
1 1 1 09-07-2013 00:01:01 IT TE NA
2 0 0 09-07-2013 10:00:00 IP TE NA
3 0 0 09-07-2013 11:00:00 IT YT NA
3 2 2 09-07-2013 11:01:00 IT YT NA
Here
Match_Status 0-->Initial Record
1-->Singel Match
2-->Multi Match
For every record there will be a initial entry with match_status 0 and subsequent matching process end other number such as 1,2 will be update.
I am trying to retrieve records such as total record , waiting match ,single match and multi match group by BO, CH and FT
Below is the expected out put:
BO CH FT TOTAL_RECORD AWAITNG_MATCH SINGLE_MATCH MULTI_MATCH
IT TE NA 1 0 1 0
IP TE NA 1 1 0 0
IT YT NA 1 0 0 2
I have tried below query :
select BO,CH,FT,sum(case when match_status=0 then 1 else 0 end) as TOTAL_RECORD,
sum(case when match_status = 0 then 1 else 0 end) as AWAITING_MATCH,
sum(case when match_status = 1 then 1 else 0 end) as SINGLE_MATCH,
sum(case when match_status = 2 then 1 else 0 end) as MULTI_MATCH from
table1 where last_update_time >= current_timestamp-1
group by BO,CH,FT;
problem with the above query is, awaiting_match is getting populated same as total record as I understand because of match_status=0
Similarly I tried with
select BO,CH,FT,sum(case when match_status=0 then 1 else 0 end) as TOTAL_RECORD,
select (sum(case when t1.ms=0 then 1 else 0 end) from
(select max(match_status) as ms from table1 where last_update_time >= current_timestamp-1 group by id)t1) )awaiting_match,
sum(case when match_status = 1 then 1 else 0 end) as SINGLE_MATCH,
sum(case when match_status = 2 then 1 else 0 end) as MULTI_MATCH from
table1 where last_update_time >= current_timestamp-1
group by BO,CH,FT;
problem with the approach is awaiting_match is getting populated with the same value for subsequent row entry.
Please help me with a suitable query for the desired format.
Thanks a lot in advance.
It seems that you want the last match status. I am guessing that this is actually the maximum of the statuses. If so, the following solves the problem by first grouping on id and then doing the grouping to summarize:
select BO, CH, FT,
count(*) as TOTAL_RECORD,
sum(case when lastms = 0 then 1 else 0 end) as AWAITING_MATCH,
sum(case when lastms = 1 then 1 else 0 end) as SINGLE_MATCH,
sum(case when lastms = 2 then 1 else 0 end) as MULTI_MATCH
from (select id, bo, ch, ft, MAX(match_status) as lastms
from table1
where last_update_time >= current_timestamp-1
group by id, bo, ch, ft
) t
group by BO, CH, FT;
If you actually want the last update to provide the status for the id, then you can use row_number() to enumerate the rows for each id, order by update time descending, and choose the first one:
select BO, CH, FT,
count(*) as TOTAL_RECORD,
sum(case when lastms = 0 then 1 else 0 end) as AWAITING_MATCH,
sum(case when lastms = 1 then 1 else 0 end) as SINGLE_MATCH,
sum(case when lastms = 2 then 1 else 0 end) as MULTI_MATCH
from (select id, bo, ch, ft, match_status,
ROW_NUMBER() over (partition by id order by last_update_time desc) as seqnum
from table1
where last_update_time >= current_timestamp-1
) t
where seqnum = 1
group by BO, CH, FT;