JOIN multiple queries from same table into one result - sql

I'm working on a question in a practical for university but can't figure out how to achieve the output I need. I am relatively new to SQL and am using Oracle 11g.
I have a single table called CUSTOMERS that I want to run three queries on to get the total count from each
CUSTOMERS (customer#, lastname, firstname, address, city, state, zip, referred, region)
The three queries on their own execute fine and produce the desired result but I need to find a way to combine them to produce a single result with three columns and the result of each query in each column.
SELECT COUNT(*) AS "Total Customers"
FROM CUSTOMERS;
SELECT COUNT(*) AS "Direct Customers"
FROM CUSTOMERS
WHERE referred IS NOT NULL;
SELECT COUNT(*) AS "Referred Customers"
FROM CUSTOMERS
WHERE referred IS NULL;
I have spent the last few hours reading here and other sites but just can't get my head around it. I suspect a JOIN or UNION may be required.

Use a single query with conditional aggregation:
SELECT
COUNT(*) AS "Total Customers",
COUNT(referred) AS "Direct Customers",
COUNT(CASE WHEN referred IS NULL THEN 1 END) AS "Referred Customers"
FROM CUSTOMERS;

Related

Get Groups of Customers Names based on their Title

Get the Count of Contact's person by their title. (Table: Customers) below:
Now, below SQL code will get group counts, but I want to add also the names associated with each group if possible please:
SELECT ContactTitle, Count(ContactTitle) FROM Customers
GROUP BY ContactTitle;
Database: This is from NorthWind database.
You can use
SELECT ContactTitle, ContactName, Count(ContactTitle) over (partition by ContactTitle) as usersCoun FROM Customers;

Usage of aggregate function Group by

I have observed that Count function can be used without the usage of aggregate function Group by. Like for example:
Select Count(*) from Employee
It would surely return the count of all the rows without the usage of aggregate function. Then where do we really need the usage of group by?
Omitting the GROUP BY implies that the entire table is one group. Sometimes you want there to be multiple groups. Consider the following example:
SELECT month, SUM(sales) AS total_sales
FROM all_sales
GROUP BY month;
This query gives you a month-by-month breakdown of sales. If you omitted month and the GROUP BY clause, you would only receive the total sales of all time which may not have the granularity you require.
You can also group by multiple columns, giving finer detail still:
SELECT state, city, COUNT(*) AS population
FROM all_people
GROUP BY state, city;
Additionally, using a GROUP BY allows us to use HAVING clauses. Which lets us filter groups. Using the above example, we can filter the result to cities with over 1,000,000 people:
SELECT state, city, COUNT(*) AS population
FROM all_people
GROUP BY state, city
HAVING COUNT(*) > 1000000;
The group by clause is used to break up aggregate results to groups of unique values. E.g., let's say you don't want to know how many employees you have, but how many by each first name (e.g., two Gregs, one Adam and three Scotts):
SELECT first_name, COUNT(*)
FROM employee
GROUP BY first_name

Beginning SQL group by and AVG

I am trying to pull information from two columns titled clientstate and clientrevenue in my table. I want clientstate to show up as the state, and have only distinct names in it, and under client revenue I want the average revenue per state, and that will only show up if there are at least two clients from that state. I am very new at this, so what I have is pretty iffy:
SELECT clientstate, clientrevenue
FROM client
GROUP BY clientrevenue
HAVING COUNT (*) >=2;
Where am I going wrong here?
SELECT clientstate AS [State]
, AVG(clientrevenue) AS [Average Revenue]
FROM client
GROUP BY clientstate
Grouping by ClientRevenue will try to group similar values and that doesn't have a logical sense.
First, in order to get distinct states, clientstate column needs to be used in the GROUP BY statement.
Thus, the code would be :
SELECT clientstate, AVG(clientrevenue)
FROM Source_Table
GROUP BY clientstate --this would get you distinct states
Now, considering the 2 clients per state, it's rather a condition than a HAVING statement. HAVING statement limits your query results according to the aggregate function you are using. For instance, in the code aforementioned, the aggregate function is AVG(clientrevenue). So, we can only use it in HAVING. we can not add count(*) unless it was used in SELECT.
So, you need to add it as a condition like
SELECT clientstate, AVG(clientrevenue)
FROM Source_Table A
WHERE (SELECT count(DISTINCT client_ID) FROM Source_Table B
WHERE A.clientstate = B.clientstate) >= 2 --Condition
GROUP BY clientstate --this would get you distinct states

How does GROUP BY use COUNT(*)

I have this query which finds the number of properties handled by each staff member along with their branch number:
SELECT s.branchNo, s.staffNo, COUNT(*) AS myCount
FROM Staff s, PropertyForRent p
WHERE s.staffNo=p.staffNo
GROUP BY s.branchNo, s.staffNo
The two relations are:
Staff{staffNo, fName, lName, position, sex, DOB, salary, branchNO}
PropertyToRent{propertyNo, street, city, postcode, type, rooms, rent, ownerNo, staffNo, branchNo}
How does SQL know what COUNT(*) is referring to? Why does it count the number of properties and not (say for example), the number of staff per branch?
This is a bit long for a comment.
COUNT(*) is counting the number of rows in each group. It is not specifically counting any particular column. Instead, what is happening is that the join is producing multiple properties, because the properties are what cause multiple rows for given values of s.branchNo and s.staffNo.
It gets even a little more "confusing" if you include a column name. The following would all typically return the same value:
COUNT(*)
COUNT(s.branchNo)
COUNT(s.staffNo)
COUNT(p.propertyNo)
With a column name, COUNT() determines the number of rows that do not have a NULL value in the column.
And finally, you should learn to use proper, explicit join syntax in your queries. Put join conditions in the on clause, not the where clause:
SELECT s.branchNo, s.staffNo, COUNT(*) AS myCount
FROM Staff s JOIN
PropertyForRent p
ON s.staffNo = p.staffNO
GROUP BY s.branchNo, s.staffNo;
GROUP BY clauses partition your result set. These partitions are all the sql engine needs to know - it simply counts their sizes.
Try your query with only count(*) in the select part.
In particular, COUNT(*) does not produce the number of distinct rows/columns in your result set!
Some people might think that count(*) really count all the columns, however the sql optimizer is smarter than that.
COUNT(*) returns the number of rows in a specified table without getting rid of duplicates. Which mean that you can't use Distinct with count(*)
Count(*) will return the cardinality (elements in table) of the specified mapping.
What you have to remember is that when using count over a specific column, null won't be allowed while count(*) will allow null in the rows as it could be any field.
How does SQL know what COUNT(*) is referring to?
I'm pretty sure, however not 100% sure as I can't find in doc, that the sql optimizer simply do a count on the primary key (not null) instead of trying to handle null in rows.

how to use distinct in ms access

I have two tables. Task and Categories.
TaskID is not a primary key as there are duplicate values.When there are multiple contacts are selected for a specific task,taskid and other details will be duplicated.I wrote the query:
SELECT Priority, Subject, Status, DueDate, Completed, Category
FROM Task, Categories
WHERE Categories.CategoryID=Task.CategoryID;
Now as multiple contacts are selected for that task,for the taskid=T4, there are two records(highlighted with gray). I have tried using distinct in ms access 2003 but its not working. I want to display distinct records. (Here there's no requirement to show taskid) If I write :
select priority, distinct(subject), .......
and remaining same as mentioned in above query then its giving me an error. I have tried distinctrow also.But didnt get success. How to get distinct values in ms access?
Okay.Its working this way.
SELECT DISTINCT Task.Priority, Task.Subject, Task.Status, Task.DueDate,
Task.Completed, Categories.Category
FROM Task, Categories
WHERE (((Categories.CategoryID)=[Task].[CategoryID]));
I don't like using SELECT DISTINCT, I have found that it makes my code take longer to compile. The other way I do it is by using GROUP BY.
SELECT Priority, Subject, Status, DueDate, Completed, Category
FROM Task, Categories
WHERE Categories.CategoryID=Task.CategoryID
GROUP BY Subject;
I do not have VBA up at the moment but this should work as well.
Using SELECT DISTINCT will work for you, but a better solution here would be to change your database design.
Duplicate records may lead to inconsistent data. For example, imagine having two different status in different records with the same TaskID. Which one would be right?
A better design would include something like a Task table, a Contact table and an Assignment table, as follows (the fields in brackets are the PK):
Tasks: [TaskID], TaskPriority, Subject, Status, DueDate, Completed, StartDate, Owner, CategoryID, ContactID, ...
Contact: [ID], Name, Surname, Address, PhoneNumber, ...
Assignment: [TaskID, ContactID]
Then, you can retrieve the Tasks with a simple SELECT from the Tasks tables.
And whenever you need to know the contacts assigned to a Tasks, you would do so using the JOIN clause, like this
SELECT T.*, C.*
FROM TaskID as T
INNER JOIN Assignment as A
ON T.TaskID = A.TaskID
INNER JOIN Contac as C
ON A.ContactID = C.ID
Or similar. You can filter, sort or group the results using all of SQL's query power.