counting number of times a particular level and then aggregating it the number of times in new variable - sql

Counting number of times a particular level (in transaction data) and then aggregating it the number of times in new variable (under one row per customer)
I have 2 levels to solicitation method, phone and email. I have created 2 new columns which count the number of times phone or email happened per id. Right now I have transaction data and cant figure out how to go about it. the data is on left, what I want is on right. I am okay with both kinds of output on right side.
So far I tried this. returns error
create table d.email as
select ID, email_count
from d.emai
where email_count = (select count (*)
from d.email
group by ID
having SolicitMethod = 'Email' );
quit;

I am not sure what you really want to do, but you can fix the syntax error by making the subquery a correlated subquery:
create table d.email as
select ID, email_count
from d.emai e
where email_count = (select count(*)
from d.email e2
where e2.SolicitMethod = 'Email' and e2.id = e.id
);
I assume the reference in the first from should be d.emai.

The first output can be obtain with this query:
It groups rows by id, and then count how many rows are on each SolicitMethod
SELECT id
, SUM(CASE
WHEN SolicitMethod = 'Email' THEN 1
ELSE 0
END) count_email
, SUM(CASE
WHEN SolicitMethod = 'phone' THEN 1
ELSE 0
END) count_phone
FROM d.email
GROUP BY id
This second output query depends of your dbms and availability of analytics function:
it count on each rows the count of sollicitMethod of each group of id
SELECT id
, SUM(CASE
WHEN SolicitMethod = 'Email' THEN 1
ELSE 0
END)
OVER (partition BY id) count_email
, SUM(CASE
WHEN SolicitMethod = 'phone' THEN 1
ELSE 0
END)
OVER (partition BY id) count_phone
FROM d.email

Related

Returning a query with columns as COUNT of a specific category from a field name

Suppose I want to return how many trips were taken by casual & member in a certain route.
https://i.stack.imgur.com/8chn5.png
SELECT
route,
COUNT(*) AS count_of_trips
FROM `fresh-ocean-357202.Cyclistic.Cyclistic_clean`
GROUP BY
route
ORDER BY
count_of_trips DESC
LIMIT 10
Try the following query (requires that your dataset includes a column named like 'User_type' or similar)
SELECT
route,
COUNT(*) AS count_of_trips,
sum(case when User_type = 'Casual_user' then 1 else 0 end) AS Casual_user_count,
sum(case when User_type = 'Member_user' then 1 else 0 end) AS Member_user_count,
FROM `fresh-ocean-357202.Cyclistic.Cyclistic_clean`
GROUP BY
route
ORDER BY
count_of_trips DESC
LIMIT 10
Please accept my answer if it covers you.

check and compare the count from two tables without relation

I have below tables
Table1: "Demo"
Columns: SSN, sales, Create_DT,Update_Dt
Table2: "Agent"
Columns: SSN,sales, Agent_Name, Create_Dt, Update_DT
Scenario 1 and desired result set:
I want output as 0 if the count of SSN in Demo table is matched with the count of SSN in Agent table
if the count is not matched then I want result as 1
Scenario 2 and desired result set:
I want output as 0 if the sum of sales in Demo table is matched with the sum of sales in Agent table
if the sum is not matched then I want result as 1
Please help on this query part
Thanks
You can write two queries separately to take counts within the result query
SELECT (SELECT count(Demo.SSN) as SSN1 from Demo)!=(SELECT count(Agent.SSN) as SSN2 from Agent) AS Result;
Basically what the inner queries does is it checked whether the counts are equal or not and outputs 1 if it is true and 0 if it is false. Since you have asked to output 1 if it is false I used '!=' sign.
You can try the same procedure in scenario 2 also
For scenario 1
select (Case when (select count(ssn) from Demo)=(select count(ssn) from Agent) then 0 else 1 end) as desired_result
If you want to count unique ssn then:
select (Case when (select count(distinct ssn) from Demo)=(select count(distinct ssn) from Agent) then 0 else 1 end) as desired_result
For scenario 2:
select (Case when (select sum(sales) from Demo)=(select sum(sales) from Agent) then 0 else 1 end) as desired_result
I would suggest one query with both sets of information:
select (d.num_ssn <> a.num_ssn) as have_different_ssn_count,
(d.sales <> a.sales) as have_different_sales
from (select count(distinct ssn) as num_ssn,
coalesce(sum(sales), 0) as sales
from demo
) d cross join
(select count(distinct ssn) as num_ssn,
coalesce(sum(sales), 0) as sales
from agent
) a;
Note: This returns boolean values -- true/false rather than 1/0. If you really want 0/1, then use case:
select (case when d.num_ssn <> a.num_ssn then 1 else 0 end) as have_different_ssn_count,
(case when d.sales <> a.sales then 1 else 0 end) as have_different_sales
It would not surprise me if you were not only interested in the total counts but also that the agent/sales combinations are the same in both tables. If that is the case, please ask a new question with a clear explanation. Sample data and desired results help.

Constructing A Query In BigQuery With CASE Statements

So I'm trying to construct a query in BigQuery that I'm struggling with for a final part.
As of now I have:
SELECT
UNIQUE(Name) as SubscriptionName,
ID,
Interval,
COUNT(mantaSubscriptionIdmetadata) AS SubsPurchased,
SUM(RevenueGenerated) as RevenueGenerated
FROM (
SELECT
mantaSubscriptionIdmetadata,
planIdmetadata,
INTEGER(Amount) as RevenueGenerated
FROM
[sample_internal_data.charge0209]
WHERE
revenueSourcemetadata = 'new'
AND
Status = 'Paid'
GROUP BY
mantaSubscriptionIdmetadata,
planIdmetadata,
RevenueGenerated
)a
JOIN (
SELECT
id,
Name,
Interval
FROM
[sample_internal_data.subplans]
WHERE
id in ('150017','150030','150033','150019')
GROUP BY
id,
Name,
Interval )b
ON
a.planIdmetadata = b.id
GROUP BY
ID,
Interval,
Name
ORDER BY
Interval ASC
The resulting query looks like this
Which is exactly what I'm looking for up to that point.
Now what I'm stuck on this. There is another column I need to add called SalesRepName. The resulting field will either be null or not null. If its null it means it was sold online. If its not null, it means it was sold via telephone. What I want to do is create two additional columns where it says how many were sold via telesales and via online. The sum total of the two columns will always equal the SubsPurchased total.
Can anyone help?
You can include case statements within aggregate functions. Here you could choose sum(case when SalesRepName is null then 1 else 0 end) as online and sum(case when SalesRepName is not null then 1 else 0 end) as telesales.
count(case when SalesRepName is null then 1 end) as online would give the same result. Using sum in these situations is simply my personal preference.
Note that omitting the else clause is equivalent to setting else null, and null isn't counted by count. This can be very useful in combination with exact_count_distinct, which has no equivalent in terms of sum.
Try below:
it assumes your SalesRepName field is in [sample_internal_data.charge0209] table
and then it uses "tiny version" of SUM(CASE ... WHEN ...) which works when you need 0 or 1 as a result to be SUM'ed
SUM(SalesRepName IS NULL) AS onlinesales,
SUM(NOT SalesRepName IS NULL) AS telsales
SELECT
UNIQUE(Name) AS SubscriptionName,
ID,
Interval,
COUNT(mantaSubscriptionIdmetadata) AS SubsPurchased,
SUM(RevenueGenerated) AS RevenueGenerated,
SUM(SalesRepName IS NULL) AS onlinesales,
SUM(NOT SalesRepName IS NULL) AS telesales
FROM (
SELECT SalesRepName, mantaSubscriptionIdmetadata, planIdmetadata, INTEGER(Amount) AS RevenueGenerated
FROM [sample_internal_data.charge0209]
WHERE revenueSourcemetadata = 'new'
AND Status = 'Paid'
GROUP BY mantaSubscriptionIdmetadata, planIdmetadata, RevenueGenerated
)a
JOIN (
SELECT id, Name, Interval
FROM [sample_internal_data.subplans]
WHERE id IN ('150017','150030','150033','150019')
GROUP BY id, Name, Interval
)b
ON a.planIdmetadata = b.id
GROUP BY ID, Interval, Name
ORDER BY Interval ASC

SQL Multiple Rows to Single Row Multiple Columns

I am including a SQLFiddle to show as an example of where I am currently at. In the example image you can see that simply grouping you get up to two lines per user depending on their status and how many of those statuses they have.
http://sqlfiddle.com/#!3/9aa649/2
The way I want it to come out is to look like the image below. Having a single line per user with two totaling columns one for Fail Total and one for Pass Total. I have been able to come close but since BOB only has Fails and not Passes this query leaves BOB out of the results. which I want to show BOB as well with his 6 Fail and 0 Pass
select a.PersonID,a.Name,a.Totals as FailTotal,b.Totals as PassTotals from (
select PersonID,Name,Status, COUNT(*) as Totals from UserReport
where Status = 'Fail'
group by PersonID,Name,Status) a
join
(
select PersonID,Name,Status, COUNT(*) as Totals from UserReport
where Status = 'Pass'
group by PersonID,Name,Status) b
on a.PersonID=b.PersonID
The below picture is what I want it to look like. Here is another SQL Fiddle that shows the above query in action
http://sqlfiddle.com/#!3/9aa649/13
Use conditional aggregation if the number of values for status column is fixed.
Fiddle
select PersonID,Name,
sum(case when "status" = 'Fail' then 1 else 0 end) as failedtotal,
sum(case when "status" = 'Pass' then 1 else 0 end) as passedtotals
from UserReport
group by PersonID,Name
Use conditional aggregation:
select PersonID, Name,
sum(case when Status = 'Fail' then 1 else 0 end) as FailedTotal,
sum(case when Status = 'Pass' then 1 else 0 end) as PassedTotal
from UserReport
group by PersonID, Name;
With conditional aggregation:
select PersonID,
Name,
sum(case when Status = 'Fail' then 1 end) as Failed,
sum(case when Status = 'Passed' then 1 end) as Passed
from UserReport
group by PersonID, Name

Want a count but it repeats 1 with every record

I want a count but it repeats 1 with every record. Can you please suggest what to do?
SELECT Count(*),
innerTable.*
FROM (SELECT (SELECT NAME
FROM tours
WHERE tours.id = tourbooking.tourid) AS NAME,
(SELECT url
FROM tours
WHERE tours.id = tourbooking.tourid) AS Url,
(SELECT TOP 1 NAME
FROM tourimages
WHERE tourimages.tourid = tourbooking.tourid
ORDER BY id ASC) AS ImageName,
(SELECT duration + ' ' + CASE WHEN durationtype = 'd' THEN
'Day(s)' WHEN
durationtype =
'h' THEN 'Hour(s)' END
FROM tours
WHERE tours.id = tourbooking.tourid) AS Duration,
(SELECT Replace(Replace('<a> Adult(s) - <c> Children', '<a>', Sum
(CASE
WHEN [type] = 1 THEN 1
ELSE 0
END)),
'<c>',
Sum(CASE
WHEN [type] = 2 THEN 1
ELSE 0
END))
FROM tourperson
WHERE tourperson.bookingid = tourbooking.id) AS TotalPassengers
,
startdate,
createddate AS BookingDate,
id AS BookingID,
[status],
serviceprice
FROM tourbooking
WHERE memberid = 6)AS innerTable
GROUP BY innerTable.NAME,
innerTable.bookingdate,
innerTable.bookingid,
innerTable.duration,
innerTable.imagename,
innerTable.serviceprice,
innerTable.startdate,
innerTable.status,
innerTable.totalpassengers,
innerTable.url
You select records from tourbooking. One of the columns you select is id. This is probably the table's primary key and thus unique. (If not, you should hurry to change that name.)
You call this ID BookingID, and it is one of the columns you group by. So you get one result record per record in tourbooking. The number of records within such a "group" is of course 1; it is the one record you select and show.
If you built real groups, say a result record per day, then you'd get a real count, e.g. the number of bookings per day.