How to create a sum of unique number and frequency - sql

Using SQL I want a report that shows how many unique calls and how many total calls was received for a given LinkedUserMailboxName. I'm unable to create a sum for 'Unique Numbers' in the query. Please help.
select count(*), UMADUserAccounts.Country as 'Country',
UMADUserAccounts.RankLevel as 'Level',
LinkedUserMailboxName,
CallingNumber as 'Unique Numbers',
count(callingnumber) as 'How many times'
from UMCallDataRecord
inner join UMADUserAccounts on
UMCallDataRecord.LinkedUserMailboxName = UMADUserAccounts.EmailAddress where
CallType = 'callansweringvoicemessage'
and
[date] between '2019-05-01' and '2019-05-31'
group by UMADUserAccounts.Country,
UMADUserAccounts.abcRankLevel,
LinkedUserMailboxName,
CallingNumber
order by
UMADUserAccounts.Country asc
Expected Output
Country Level LinkedUserMailboxName Unique Numbers How many times
USA Associate Alexia.b#ca.abc.com 2 2
USA Associate Angelina.asas#de.abc.com 2 2
USA Associate Asad.slob#ca.abc.com 2 2
USA Associate Austin.jones#ca.abc.com 3 3
USA Associate Bankole.smith#ca.abc.com 3 13
Output
Country Level LinkedUserMailboxName Unique Numbers How many times
USA Associate Alexia.b#ca.abc.com +11232561600 1
USA Associate Alexia.b#ca.abc.com +11235712476 1
USA Associate Angelina.asas#de.abc.com +49132433113287 1
USA Associate Angelina.asas#de.abc.com daniel.boy#abc.com 1
USA Associate Asad.slob#ca.abc.com +11255722196 1
USA Associate Asad.slob#ca.abc.com terry.q.public#abc.com 1
USA Associate Austin.jones#ca.abc.com +11239840743 1
USA Associate Austin.jones#ca.abc.com +11239543735 1
USA Associate Austin.jones#ca.abc.com +11234325015 1
USA Associate Bankole.smith#ca.abc.com +112355810290 1
USA Associate Bankole.smith#ca.abc.com +11233508936 1
USA Associate Bankole.smith#ca.abc.com +11237477000 11

I think you want count(distinct):
select count(*), ua.Country as Country, ua.RankLevel as Level,
LinkedUserMailboxName,
count(distinct CallingNumber) as Unique_Numbers,
count(*) as how_many_times
from UMCallDataRecord cdr inner join
UMADUserAccounts ua
on cdr.LinkedUserMailboxName = ua.EmailAddress
where cdr.CallType = 'callansweringvoicemessage' and
cdr.[date] >= '2019-05-01' and
cdr.[date] < '2019-06-01'
group by ua.Country, ua.abcRankLevel, LinkedUserMailboxName,
order by ua.Country asc;
Notes:
Table aliases make the query easier to write and to read.
Qualify all column references, particularly when the query refers to more than one table.
I removed the between for the date comparisons. Aaron Bertrand has a good explanation of why you should avoid between in this case.

Related

Counting prefixes in a joined table in SQL

I am trying to count how many makes of car a person owns. Car makes are only defined by a prefix in my Links table.
Table 1 (Person)
UniqueID Name
PER0001 Adrian
PER0002 Michael
Per0003 James
Table 2 (Links)
UniqueID LinkEnd1_ID LinkEnd2_ID
LIN0001 PER0001 FER02332
LIN0002 PER0001 FER02112
LIN0003 PER0001 POR12122
LIN0004 PER0002 FER12321
LIN0005 PER0003 MAS12382
LIN0006 PER0003 FER22982
LIN0006 PER0003 MAS12232
Output (option 1)
Name Car_Make Count
Adrian FER 2
Adrian POR 1
Michael FER 1
James MAS 2
James FER 1
Output (option 2 - preferred)
Name FER POR MAS
Adrian 1 2
Michael 1
James 1 2
The reason I am using a link table to count the number of car makes is because every car make has a different table I would need to join in.
I've tried
select count left(LinkEnd2_ID,3) which doesnt work, i've also tried group by which I cant seem to crack.
I guess what I want to be able to do is
select
count(left(LinkEnd2_ID,3)='FER'
,count(left(LinkEnd2_ID,3)='POR'
,count(left(LinkEnd2_ID,3)='MAS'
but thats a query in a select and I decipher how to code that properly.
Heres where I am starting from (or the base I keep going back to start afresh)-
SELECT
Person.Unique_ID
,Person.Name
,left(Link.LinkEnd2_ID,3) as Car_Make
FROM
Person
LEFT JOIN
Links as Link
on Person.Unique_ID = Link.LinkEnd1_ID
Any help you can offer would be appreciated.
Nearly there, you just need to add a group by, and change all the columns to aggregate functions.
Your option 1:
SELECT
max(Person.Name) as Person_Name
,left(Link.LinkEnd2_ID,3) as Car_Make
,count(*) as No_of_Car
FROM
Person
LEFT JOIN
Links as Link
on Person.Unique_ID = Link.LinkEnd1_ID
GROUP BY
Person.Unique_ID
For your option 2, you need to wrap your aggregate functions around case statements
you have to hardcode the 3 different car make, so if you have unknown number of them, it wouldn't work.
SELECT
max(Person.Name) as Person_Name
,sum(case when left(Link.LinkEnd2_ID,3) ='FER' then 1 else 0 end) as FER
,sum(case when left(Link.LinkEnd2_ID,3) ='POR' then 1 else 0 end) as POR
,sum(case when left(Link.LinkEnd2_ID,3) ='MAS' then 1 else 0 end) as MAS
FROM
Person
LEFT JOIN
Links as Link
on Person.Unique_ID = Link.LinkEnd1_ID
GROUP BY
Person.Unique_ID

SQL row names and row flags

I have trouble understanding row flags. The below question can clear it for me:
Is it possible to store a name and its flag in the same cell in SQL?
Consider:
If you have a table known as cars with the columns number_plate, colour, and brand_name. The brand_name has a name and a flag.
How would one store that in a single column? If it is not possible or advised, explain why and how to do it.
How would you then get the number of cars from a given country (based on the unique number_plate(primary key)) and the country flag?
I think you are trying to design a schema but haven't quite got the hang of foreign keys.
In your example, you'd have the following tables:
country:
country_id name continent
-----------------------------------
1 Germany Europe
2 Japan Asia
3 USA N.America
Brand
Brand_id name country_id (foreign key)
---------------------------------------------
1 Mercedes 1
2 Toyota 2
3 BMW 1
4 Chrysler 3
Car
Number_plate colour brand_id
------------------------------------------
xxx-yy-zz Green 1
aa-bb-cc Red 1
kkk-l-mmm Orange 2
....
To find the number of cars, based on the country where the brand is based, you'd do something like:
select country.name,
count(*)
from car
inner join brand on car.brand_id = brand.brand_id
inner join country on brand.country_id = country.country_id
group by country.name
Let's say name and flag are two separate columns. Using concat function they can be stored into a single column named brand_name.
select number_plate, colour, concat(name,' ',flag) as brand_name from cars
To get the count of cars(unique) based on a flag
select * from
(select
distinct number_plate,
colour,
concat(name,' ',flag) as brand_name from cars
) a
where brand_name like '%UK%'
Demo

SQL (COUNT(*) / locations.area)

We are learning SQL at school, and my professor has this sql code in his documents.
SELECT wp.city, (COUNT(*) / locations.area) AS population_density
FROM world_poulation AS wp
INNER JOIN location
ON wp.city = locations.city
WHERE locations.state = “Hessen”
GROUP BY wp.city, locations.area
Everything is almost clear for me, just the aggregate function with /locations.area doesn't make any sense to me. Can anybody help?
Thank you in advance!
Look at what the query is grouped on, that tells you what each group consists of. In this case, each group is a city, and contains all the rows that have the same value for wp.city (and as the location table is joined on that value too, the locations.area is only included in the grouping so that it can be used in the result).
So each group has a number of rows, and the COUNT(*) aggregate will contain the number of rows for each group. The value of (COUNT(*) / locations.area) will be the number of rows in the group divided by the value of locations.area for that group.
If you would have data like this:
world_population
name city
--------- ---------
John London
Peter London
Sarah London
Malcolm London
Ian Cardiff
Johanna Stockholm
Sven Stockholm
Egil Stockholm
locations
city state area
----------- -------------- ---------
London Hessen 2
Cardiff Somehere else 14
Stockholm Hessen 1
Then you would get a result with two groups (as Cardiff is not in the state Hessen). One group has four people from London which has the area 2, so the population density would be 2. The other group has three people from Stockholm which has the area 1, so the population density would be 3.
Side note: There is a typo in the query, as it joins in the table location but refers to it as locations everywhere else.
Try writing it like:
SELECT wp.city,
locations.area,
COUNT(*) AS population,
(COUNT(*) / locations.area) AS population_density
FROM world_poulation AS wp
INNER JOIN location
ON wp.city = locations.city
WHERE locations.state = “Hessen”
GROUP BY wp.city, locations.area
The key is the GROUP BY statement. You are showing pairs of cities and areas. The COUNT(*) is the number of times a given pair shows up in the table you created by joining world population and location. The area is just a number, so you can divide the area by the COUNT.

Selecting more after group-by while using join

At the moment I am busy with two tables, Students and Classes. These two both contain a column project_group, a way to categorize multiple students from one class into smaller groups.
In the Students table there is a column City that states in which town/city students live, from the rows that have been filled there are already several cities occurring multiple times. The code I used to check how many times a city is being showed is this:
SELECT City, count(*)
FROM Students
GROUP BY City
Now the next thing I want to do is show per class in which cities the students live and how many live there, so for example a result like:
A | - | 2
A | New York | 3
A | Los Angeles | 1
B | - | 1
B | Miami | 2
B | Seattle | 1
Students and Classes can join each other on the column project_group but what I'm mostly interested in his using both the GROUP BY mentioned earlier, using the JOIN and also showing the results per class.
Thanks in advance,
KRAD
I'm not sure what the column name is for A and B in your example. I'm assuming Classes.Class in the following:
SELECT
C.Class
, S.City
, COUNT(S.*) AS Count
FROM
Classes AS C INNER JOIN
Students AS S ON C.Project_Group = S.Project_Group
GROUP BY
C.Class
, S.City
I managed to get it working. While doing some tests to see which exact error message it was that I got, I used this and managed to get it working. I now get an overview per class that shows how many people live in which city. This is the code used.
SELECT class_id, city, count(*) AS amount
FROM students, classes
WHERE students.project_group = classes.project_group
GROUP BY class_id, city
ORDER BY class_id

statistic syntax in access

I want to do some statistic for the Point in my appliation,this is the columns for Point table:
id type city
1 food NewYork
2 food Washington
3 sport NewYork
4 food .....
Each point belongs to a certain type and located at the certain city.
Now I want to caculate the numbers of points in different city for each type.
For example, there are two types here :food and sport.
Then I want to know:
how many points of `food` and `sport` at NewYork
how many points of `food` and `sport` at Washington
how many points of `food` and `sport` at Chicago
......
I have tried this:
select type,count(*) as num from point group by type ;
But I can not group the by the city.
How to make it?
Update
id type city
1 food NewYork
2 sport NewYork
3 food Chicago
4 food San
And I want to get something like this:
NewYork Chicago San
food 2 1 1
sport 1 0 0
I will use the html table and chart to display these datas.
So I need to do the counting, I can use something like this:
select count(*) from point where type='food' and city ='San'
select count(*) from point where type='food' and city ='NewYork'
....
However I think this is a bad idea,so I wonder if I can use the sql to do the counting.
BTW,for these table data,how do people organization their structure using json?
this's what you want:
SELECT city,
COUNT(CASE WHEN [type] = 'food' THEN 1 END) AS FoodCount,
COUNT(CASE WHEN [type] = 'sport' THEN 1 END) AS SportCount
FROM point
GROUP BY city
UPDATE:
To get the results in an aggregated row/column format you need to use a pivot table. In Access it's called a Crosstab query. You can use the Crosstab query wizard to generate the query via a nice UI or cut straight to the SQL:
TRANSFORM COUNT(id) AS CountOfId
SELECT type
FROM point
GROUP BY type
PIVOT city
The grouping is used to count the number of Id's for each type. The additional PIVOT clause groups the data by city and displays each grouping in a separate column. The end result looks something like this:
NewYork Chicago San
food 2 1 1
sport 1 0 0