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

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.

Related

Count the occurrences of a given list of values in a column using a single SQL query

I would like to get the count of occurrences of a given list of values in a column using a single SQL query. The operations must be optimised for performance.
Please refer the example given below,
Sample Table name - history
code_list
5lysgj
627czl
1lqnd8
627czl
dtrtvp
627czl
esdop9
esdop9
3by104
1lqnd8
Expected Output
Need to get the count of occurrences for these given list of codes 627czl, 1lqnd8, esdop9, aol4m6 in the format given below.
code
count
627czl
3
esdop9
2
1lqnd8
2
aol4m6
0
Method I tried in show below but the count of each input is shown as a new column using this query,
SELECT
sum(case when h.code_list = 'esdop9' then 1 else 0 end) AS count_esdop9,
sum(case when h.code_list = '627czl' then 1 else 0 end) AS count_627czl,
sum(case when h.code_list = '1lqnd8' then 1 else 0 end) AS count_1lqnd8,
sum(case when h.code_list = 'aol4m6' then 1 else 0 end) AS count_aol4m6
FROM history h;
Note - The number inputs need to be given in the query in 10 also the real table has millions of records.
If i properly understand you need to get the count of occurrences for the following codes: 627czl, 1lqnd8, esdop9.
In this case you can try this one:
SELECT code_list, count(*) as count_
FROM history
WHERE code_list in ('627czl','1lqnd8','esdop9')
GROUP BY code_list
ORDER BY count_ DESC;
dbfiddle
If you need to get the count of occurrences for all codes you can run the following query:
SELECT code_list, count(*) as count_
FROM history
GROUP BY code_list
ORDER BY count_ DESC;
you can try to use GROUP BY
Something like this
SELECT code_list, COUNT(1) as 'total' ROM h GROUP by code_list order by 'total' ;

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

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

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

I want a case statetement that count more than 1 as 1

Please help solve the below query.
The column in question has Y and N and I want the N to show zero and the Y to show 1.
I want it to aggregate the no of times visited for each machine and if >= 1 to show 1. Client requirement is whether machine has been visited regardless of the number of times.
Select MachineNo,
[Date_of_Visit],
Month([Date_of_Visit])[Month],
Year([Date_of_Visit])[Year],
sum(case when [Visited] = 'Y' then 1 else 0 end)[No of Visits]
FROM [MachineVisit]
Group by [Date_of_Visit],
[MachineNo]
Use Max instead of Sum
Max(case when [Visited] = 'Y' then 1 else 0 end)[Visits]
This is a little confusing, the way it is written, but I am assuming you want something like:
select sum(case when [visited] >1 then 1 else null end) visists
from visit_table
where visit_date = '2015-01-30'
This is assuming that you have a table that counts the visits for a single day for 1 IP address as single entry.
If you have a table that has an entry for every single page visit, then you would probably need to do:
select count(distinct ip_address)
from (
select ip_address
from visit_table
where visit_date = '2015-01-30'
group by ip_address
having count(1) >1
) x
EDIT:
Well then the simplist way should be:
select count(1)
from visit_table
where [visited]='Y'
and visit_date = '2015-01-30'
;
That should work...
Although I don't have the table in front of me - so if this doesn't work, please post the fully query.