How to use subquery in sql server 2008? - sql

I know this question might be repeated ... But I have query like this, I have a field "Compute_CRM_State" in my table. And that field contains data like "approved,pending,cancelled" but now i want to fetch total count of approved or pending or cancelled. I tried it with sub query. I can able to get total count of approved or pending or cancelled but.. I got same records many times.
query :
SELECT (SELECT COUNT(Compute_CRM_State) AS Expr1
FROM CRM_Doctor_Request
WHERE (CRM_State_Id = 1)) AS PENDING,
(SELECT COUNT(Compute_CRM_State) AS Expr2
FROM CRM_Doctor_Request AS CRM_Doctor_Request_3
WHERE (CRM_State_Id = 2)) AS Approved,
(SELECT COUNT(Compute_CRM_State) AS Expr3
FROM CRM_Doctor_Request AS CRM_Doctor_Request_2
WHERE (CRM_State_Id = 3)) AS CANCELLED
FROM CRM_Doctor_Request AS CRM_Doctor_Request_1
There should be display only 1 record of count.. but it is getting display the number of times that number of records in table contains.

The reason you were not getting the total count correctly and getting many records instead, is that the COUNTs are selected as a correlated subquery, so you will got the count for each record in the table.
To fix that you have to use the aggregate function in the outer query, not from the correlated subuery. And to get those total count for each status, use the CASE expression to do this like so:
SELECT
SUM(CASE WHEN CRM_State_Id = 1 THEN 1 ELSE 0 END) AS PENDING,
SUM(CASE WHEN CRM_State_Id = 2 THEN 1 ELSE 0 END) AS Approved,
SUM(CASE WHEN CRM_State_Id = 3 THEN 1 ELSE 0 END) AS CANCELLED
FROM CRM_Doctor_Request;
SQL Fiddle Demo
Or: you can use the PIVOT table operator to do the same thing:
SELECT
[1] AS PENDING,
[2] AS Approved,
[3] AS Cancelled
FROM
(
SELECT * FROM CRM_Doctor_Request
) AS t
PIVOT
(
COUNT(Compute_CRM_State)
FOR CRM_State_Id IN([1], [2], [3])
) AS p;
Like this.

Related

Is there a way to collect the data and inspect in one pass using groupby function

Sample Data of table_1
Have this Query that returns
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0 END) AS num_activity_a_or_b
from table_1
group by customer
Results:
Want to extend this to return one more column if for a given code say X1 if the Activity is "a" and "c" then return num_of_a_and_c_activity.
A bit stuck how to collect and inpect the code and activities in one pass.
can we combine windowing function to achieve this.
Please advise and help
UPDATE:
based on the updated results, maybe the below query is what you need
So what i assume is that you need both a and c as well x1 .
So I count distinct activities which are a and c and then do integer division by 2. if only a is present then count distinct =1 but 1/2 =0 in integer division.
It is only 1 when both a and c are present.
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0
END) AS num_activity_a_or_b,
COUNT(DISTINCT CASE WHEN code IN ('x1') AND activity IN ( 'a','c')
THEN activity
ELSE NULL
END)/2 AS num_activity_a_and_c
from table_1
group by customer
Maybe your query can be
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0
END) AS num_activity_a_or_b,
SUM(CASE WHEN code IN ('x1') AND activity IN ( 'a','c')
THEN 1
ELSE 0
END) AS num_activity_a_or_c
from table_1
group by customer

GROUP BY with COUNT condition

I have a result set such as:
Code No
1 *
1 -
1 4
1
1
Now i basically want a query that has 2 columns, a count for the total amount and a count for those that dont have numbers.
Code No_Number Total
1 4 5
Im assuming this needs a group by and a count but how can i do the 2 different counts in a query like this?
This is what i had so far, but i am a bit stuck with the rest of it
SELECT CODE,NO
Sum(Case when No IN ('*', '-', '') then 1 else 0 end) as Count
I think you basically just need GROUP BY:
SELECT CODE,
SUM(Case when No IN ('*', '-', '') then 1 else 0 end) as Count,
COUNT(*) as total
FROM t
GROUP BY CODE;
Well, this took a moment :-), however here it is...I have used a CASE statement to create and populate the No_Number column; the database gives the row in the original table a value of 1 if the original table value is a number or gives it a NULL and discards it from the COUNT if not. Then when it makes the count it is only recognising values which were originally numbers and ignoring everything else..
If the result set is in a table or temp table:
SELECT Code,
COUNT(CASE WHEN [No] NOT LIKE '[0-9]' THEN 1 ELSE NULL END) AS No_Number,
COUNT(Code) AS Total
FROM <tablename>
GROUP BY Code
If the result set is the product of a previous query you can use a CTE (Common Table Expression) to arrive at the required result or you could include parts of this code in the earlier query.

How to do a COUNT with a WHERE clause?

I actually have a query joining 3 tables to collect informations so I can calculate some KPIs, but my logic is flawed, here is my actual query :
SELECT t.idCustomer, t.nameCustomer
COUNT(DISTINCT t.idTrip),
SUM(
CASE
WHEN t.tripDone <> 1
THEN 1
ELSE 0
END),
SUM(CASE
WHEN t.codeIncident = 'CANCEL'
THEN 1
ELSE 0
END)
FROM
(SELECT customer.idCustomer, customer.nameCustomer, trip.tripDone, incident.codeIncident
FROM CUSTOMER customer
JOIN TRIP trip ON customer.idCustomer = trip.idCustomer
JOIN INCIDENT incident ON trip.idTrip = incident.idTrip) t
GROUP BY t.idCustomer, t.nameCustomer
So, I want to know for each Customer :
COUNT(DISTINCT t.idTrip) -> The number of trips by this customer
Sum when t.tripDone <> 1 -> The number of trips that are done by this customer ( not ingoing )
Sum when t.codeIncident = 'CANCEL' -> The number of trips by this customer where there was a cancellation.
The big mistake I made here, is that a trip can have multiple codeIncidents (example : one record for an idTrip with the codeIncident 'CANCEL' and another record with same idTrip with the codeIncident 'DELAYED'), so when I calculate the Sum when t.tripDone <> 1 I get a result of : '2' instead of '1' (because there are 2 records in my from Clause that have the t.tripDone <> 1 for the same idTrip).
Would you have any idea on how I should process this query so I can do the Sum when tripDone <> 1 only once for each tripId ?
Thanks a lot for the help !
If you need some more infos I'm available, and sorry for my lack of english skills !
It sounds like you want to do the same count(distinct ...) pattern for the columns you're currently summing, but with some logic. You can use case within a count instead in the same way:
...
COUNT(
DISTINCT CASE
WHEN t.tripDone <> 1
THEN t.idTrip
ELSE null
END),
COUNT(
DISTINCT CASE
WHEN t.codeIncident = 'CANCEL'
THEN t.idTrip
ELSE null
END)
The else null is a bit redundant as that's the default. As count() ignores nulls, if the when isn't matched then that trip ID isn't counted.
First Select idTrip field in your inner query that means table "t"

How to group and get count of rows based on value of one column in sql server

I have a table of requests with columns RequestType,status .Status column values can be in-progress,complated etc.
I would like to get the list like
RequestType In-Progress Completed Total
Type1 10 5 15
Type2 10 10 20
I tried with group by using the 2 columns( RequestType,status) ,but it does not give me the exact result.
Please help me with the sql query.
Thanks in advance
Subin
One way to do it is using conditional aggrigation:
SELECT RequestType,
SUM(CASE WHEN Status = 'In-Progress' THEN 1 ELSE 0 END) As 'In-Progress',
SUM(CASE WHEN Status = 'Completed' THEN 1 ELSE 0 END) As 'Completed',
COUNT(Status) As 'Total'
FROM TableName
WHERE Status IN('In-Progress', 'Completed')
GROUP BY RequestType
Use PIVOT
select *, [In-Progress]+[Completed] total
from TableName
pivot ( count(status) for status in ([In-Progress], [Completed])) as p

Sum distinct records in a table with duplicates in Teradata

I have a table that has some duplicates. I can count the distinct records to get the Total Volume. When I try to Sum when the CompTia Code is B92 and run distinct is still counts the dupes.
Here is the query:
select
a.repair_week_period,
count(distinct a.notif_id) as Total_Volume,
sum(distinct case when a.header_comptia_cd = 'B92' then 1 else 0 end) as B92_Sum
FROM artemis_biz_app.aca_service_event a
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
group by 1
order by 1
;
Is There a way to only SUM the distinct records for B92?
I also tried inner joining the table on itself by selecting the distinct notification id and joining on that notification id, but still getting wrong sum counts.
Thanks!
Your B92_Sum currently returns either NULL, 1 or 2, this is definitely no sum.
To sum distinct values you need something like
sum(distinct case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end)
If this column_to_sum is actually the notif_id you get a conditional count but not a sum.
Otherwise the distinct might remove too many vales and then you probably need a Derived Table where you remove duplicates before aggregation:
select
repair_week_period,
--no more distinct needed
count(a.notif_id) as Total_Volume,
sum(case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end) as B92_Sum
FROM
(
select repair_week_period,
notif_id
header_comptia_cd,
column_to_sum
from artemis_biz_app.aca_service_event
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
-- only onw row per notif_id
qualify row_number() over (partition by notif_id order by ???) = 1
) a
group by 1
order by 1
;
#dnoeth It seems the solution to my problem was not to SUM the data, but to count distinct it.
This is how I resolved my problem:
count(distinct case when a.header_comptia_cd = 'B92' then a.notif_id else NULL end) as B92_Sum