SQL List the representative that handles the most customers - sql

I have 2 tables SALESREP and CUSTOMER
I need to find out which salesrep has most customers
I have the following code:
select rep_lname, count(cust_num)
from customer inner join salesrep
on customer.REP_NUM = SALESREP.REP_NUM
group by rep_lname
This gives me all the rows with the number of customers each salesrep has, instead I need only one row that has the most customers.
How can I find the row with MAX num of customers?

select rep_lname, count(cust_num)
from customer inner join salesrep
on customer.REP_NUM = SALESREP.REP_NUM
group by rep_lname order by count(cust_num) desc limit 1;
I'm sure there's another way using having, but I can't seem to figure it out at the moment. Perhaps somebody else will chime in with it?

SELECT TOP 1 WITH TIES rep_lname, COUNT(cust_num)
FROM customer inner join salesrep
ON customer.REP_NUM = SALESREP.REP_NUM
GROUP BY rep_lname
ORDER BY count(cust_num) DESC

Related

SELECT "NOT IN", INNER JOIN and COUNT in SQL Query

I am trying to select which co-ordinates from OA table are NOT found in the CUSTOMER address table.
SELECT DISTINCT
OA.CO_ORDS
FROM
CUSTOMER
INNER JOIN
OA ON customer.address=oa.co_ords
ORDER BY ID ASC;
Returns the co-ordinates which ARE in the customer table. How do I return those that are not in the customer table?
Am I also able to COUNT how many of customers are is in each co-ordinate (The co-ords are not specific and not accurate, this is purely for query testing only)
SELECT DISTINCT
OA.CO_ORDS
FROM
CUSTOMER
INNER JOIN
OA ON customer.address=oa.co_ords
ORDER BY ID ASC;
We can use NOT EXISTS to find those co-ordinates which don't appear in the customer table:
SELECT co_ords
FROM oa
WHERE
NOT EXISTS
(SELECT 1 FROM customers
WHERE address = oa.co_ords)
ORDER BY id;
In order to count how many customers belong to a certain co-ordinate, we can use COUNT with GROUP BY, something like this:
SELECT c.address, COUNT(*)
FROM customers c
JOIN oa
ON c.address = oa.co_ords
GROUP BY c.address;
It could be better to count a specific column instead of *.
It could also be better to use an IN clause instead of JOIN the tables:
SELECT c.address, COUNT(*)
FROM customers c
WHERE address IN
(SELECT co_ords FROM oa)
GROUP BY c.address;
Such details depend on your exact table structure, you should please try this out or provide more details.
You could also do:
SELECT co_ords
FROM oa
MINUS
SELECT address
FROM customers;
which can sometimes be faster than doing an anti-join. Note that MINUS does a distinct on the resultset.

(Simple?) SQL Query: Display all customer information for customers with 2+ orders

I'm doing practice exam material for a distance education course. I have the following three relations (simplified here):
salesperson(emp#, name, salary)
order(order#, cust#, emp#, total)
customer(cust#, name, city)
I'm stuck on a pair of SQL queries.
Display all customer info for customers with at least 1 order.
SELECT * FROM customer
INNER JOIN order ON order.cust# = customer.cust#
GROUP BY cust#;
Display all customer info for customers with at least 2 orders.
SELECT cust#, name, city, industry-type FROM customer
INNER JOIN order ON order.cust# = customer.cust#
GROUP BY cust#
HAVING COUNT(cust#) > 2;
I realize these are misguided attempts resulting from a poor understanding of SQL, but I've spent a ton of time on W3School's SQL Query example tool (https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_where) without getting anywhere, and I finally need some "real" help.
You can try to use subquery to get count by cust# then do inner join to make it.
SELECT c.*
FROM (
SELECT cust# , COUNT(*) cnt
FROM order
GROUP BY cust#
) o INNER JOIN customer c ON c.cust# = o.cust#
WHERE o.cnt > 2
You can change table names according to your DB. Following queries you can directly run in W3Schools
Display all customer info for customers with at least 1 order.
SELECT * FROM customers as cust JOIN orders as o ON o.customerid =
cust.customerid GROUP BY o.customerid;
Display all customer info for customers with at least 2 orders.
SELECT * FROM customers as cust JOIN orders as O ON O.CustomerID = cust.CustomerID GROUP BY cust.CustomerID HAVING COUNT(cust.CustomerID) > 2;

Group By a Specific Column

I had this query that was working fine...
select a.action_id, a.request_date, a.customer_id from customer.actions a
inner join customer.customers c on c.id = a.customer_id
inner join customer.entities e on e.id = c.entity_id
where request_url like '%/test%'
order by a.request_date desc;
This returned +- 500 lines. Now I wanted to inner join with another table but it's returning like 4000 lines..
select a.action_id, a.customer_id, a.request_date, mp.payment_type from customer.actions a
inner join customer.customers c on c.id = a.customer_id
inner join customer.entities e on e.id = c.entity_id
inner join customer.mobile_payments mp on mp.customer_id = a.customer_id
where request_url like '%/test%'
order by a.request_date desc;
I get duplicate records for every record on the mobile_payments table.
Group by does not work
How do I remove the duplicate action_ids ? DISTINCT (a.action_id) doesn't work
EDIT:
I just want the records from the customer.actions filtered by where request_url like '%/test%' and I want to get the payment type from the mobile_payments table. 1 for each action_id. When I do that I get duplicate actions ids.
As accurately pointed out by J0eBl4ck in comment, the issue is that you are joining to the payments table on the sole condition of matching customer. Think of it like this. You have a credit card for purchases over 10 years. Each month you make a payment, so you have 120 payments made under your account.
Is there some other basis you are joining to the payment table? You have an action ID? Does that mean something? Do you intend to get a payment associated to that specific action? Is there such a relationship where it would be
customer -> payments joined on customer_id AND action_id?
A secondary option is to apply a sub-query from the payments table grouped by the customer id so it only returns a single row, this way it does not distort your overall record count. You may need to adjust the underlying criteria some, but this should help you look into final resolution to your needs.
select
a.action_id,
a.customer_id,
a.request_date,
mp.payment_type
from
customer.actions a
inner join customer.customers c
on a.customer_id = c.id
inner join customer.entities e
on c.entity_id = e.id
inner join
-- this "PQ" Pre-Query is by customer ID and example
-- to get the payment type based on whatever the most recent
-- transaction in first position
( select mp.customer_id,
mp.payment_type,
row_number() over (partition by mp.customer_id
order by mp.WhateverPrimaryKeyOrDateIs DESC ) as rowSeq
from
customer.mobile_payments mp ) PQ
-- so here, we are only joining on the FIRST (most recent due to descending)
-- payment type applicable for the customer ID in question joined to
on a.customer_id = PQ.customer_id
AND PQ.rowSeq = 1
where
request_url like '%/test%'
order by
a.request_date desc;
Again, you WILL probably need to adjust the pre-query as we dont get the context association of payment to a given action. Hopefully it will guide you in your final goal though.

MS ACCESS / SQL: Select maximum count per person, per variable

In MS Access, I've joined two tables, one table is a list of sales and the city they took place (Sales), and another is a table of persons and the sales their participated in (SalePersons).
When joining the two tables, you can see that the combined table details many sales per person across many cities. My goal is obtain the most-frequented city for sales per each person.
For example, Customer 1 might have 2 sales in Baltimore, 1 sale in New York, and 3 Washington; customer 2 might have 3 sales in Washington, 4 sale in Wichita, and 1 sale in New York. The table needs to have only "Washington" listed for Customer 1, and only "Wichita" listed for Customer 2. If there's a tie, I'd like to list all the tied cities.
So far, I only have the initial join working.
SELECT SalePersons.PersonID, Count(Sales.SaleNum) AS CountOfSaleNum, Sales.CITY
FROM Sales INNER JOIN SalePersons ON Sales.SaleNum = SalePersons.SaleNum
GROUP BY SalePersons.PersonID, Sales.CITY;
But, as you might guess, this join will only give me the count of sales per city, per person across all cities. I need to retrieve only the 1 most-frequented city person.
I thought I could make this a subquery and wrap all this all under a Select MAX(CountOfSaleNum) clause, but that didn't work. I still have much to learn.
Thank you in advance! I don't know what I'd do without this site sometimes.
You can use window functions:
SELECT sp.*
FROM (SELECT sp.PersonID, COUNT(*) AS CountOfSaleNum, s.CITY,
ROW_NUMBER() OVER (PARTITION BY sp.PersonID ORDER BY COUNT(*) DESC) as seqnum
FROM Sales s INNER JOIN
SalePersons sp
ON s.SaleNum = sp.SaleNum
GROUP BY sp.PersonID, s.CITY
) sp
WHERE seqnum = 1;
In MS Access, you are stuck with a more complicated query:
SELECT sp.PersonID, COUNT(*) AS CountOfSaleNum, s.CITY
FROM Sales as s INNER JOIN
SalePersons as sp
ON s.SaleNum = sp.SaleNum
GROUP BY sp.PersonID, s.CITY
HAVING s.City = (SELECT TOP 1 s2.City
FROM Sales as s2 INNER JOIN
SalePersons as sp2
ON s2.SaleNum = sp2.SaleNum
WHERE sp2.PersonID = sp.PersonId
GROUP BY sp2.PersonId, s2.City
ORDER BY COUNT(*) DESC, s2.City
);

Return customers with no sales

I'm a bit of a beginner with SQL so apologies if this seems trivial/basic. I'm struggling to get my head around it...
I am trying to generate results that show all customers that are in the customer table that have never placed an order and will therefore have no entry on the invoice table.
In other words, I want to select all customers from the customer table where there is no entry for their customer number in the invoice table.
Many thanks,
Mike
SELECT *
FROM customer c
WHERE NOT EXISTS (
SELECT 1
FROM invoice i
WHERE i.customerid = c.customerid
)
I would suggest you also read Oracle's documentation on different types of table joins here.
if customer_id is the collumn that identify the customer you should do something like this...
select * from Customer
where customer_id not in (select customer_id from invoice)
If you want to return all customer rows, then you will want to use a LEFT JOIN
select *
from customer c
left join invoices i
on c.customerid = i.customerid
where i.customerid is null
See SQL Fiddle with Demo
If you need help learning JOIN syntax, then here is a great visual explanation of joins.
A LEFT JOIN will return all rows from the customer table even if there is not a matching row in the invoices table. If you wanted to return only the rows that matched in both tables, then you would use an INNER JOIN. By adding the where i.customerid is null to the query it will return only those rows with no match in invoices.