Getting distinct count in SQL Server - sql

I have three tables:
companies
customers for those companies
addresses for each customer
I want to know how many companies in my database has the accounts with more that 100 addresses linked to them.
I tried this but it didn't work:
SELECT
COUNT(DISTINCT c.Id)
FROM
Customers cu
INNER JOIN
Addresses ad ON ad.Customer = cu.Id
INNER JOIN
Companies c ON cu.company = c.Id
GROUP BY
cu.ID
HAVING
COUNT(ad.ID) > 100

You need two levels of aggregation for this query. Here is one method:
SELECT COUNT(*)
FROM (SELECT cu.company, COUNT(DISTINCT ad.id) as num_accresses
FROM Customers cu
INNER JOIN Addresses ad ON ad.Customer = cu.Id
GROUP BY cu.company
HAVING COUNT(DISTINCT ad.id) > 100
) cua;
The inner query returns the companies that have more than 100 addresses. Note the use of COUNT(DISTINCT). Presumably, two "customers" could have the same addresses.
Also, the companies table is not needed. The identifying information is in customers. You are only looking for a count, so the table is not necessary.

Related

How to query customers data with different customer levels in Postgresql?

Currently, I encounter with running query in Posgtresql server, there are 3 tables which contain customer information, customers who apply membercard and customers payment as below:
table customer
customerid, name, lastname, age
table payment
customerid, payment, product, date
table membercard
customerid, membercardno, createddate, status
In my system, there are 2 kind of customers such as regular and member customers.
Regular customers are those customers that haven't applied to be member customers yet.
Member customers are those customers that already applied to be customers.
In this scenario, I would like to query all of 2 kind customers in these 3 tables.
ex: customerid, name, lastname, age, membercardno, payment, product, date
For my query:
SELECT C.CUSTOMERID, C.NAME, C.LASTNAME, C.AGE,
M.MEMBERCARDNO, P.PAYMENT, P.PRODUCT, P.DATE
FROM CUSTOMER C,
MEMBERCARD M,
PAYMENT P
WHERE C.CUSTOMERID = M.MEMBERCARD AND
C.CUSTOMERID = P.CUSTOMERID
ORDER BY CUSTOMERID
in this case, just can query only those customers are member customers.
How to query both kind of customers? it's very hard to do for me.
Any help from our expert will be very appreciate.
You need to use an OUTER JOIN to pull in the membercard data, because not all customers have a member card.
SELECT C.CUSTOMERID, C.NAME, C.LASTNAME, C.AGE,
M.MEMBERCARDNO, P.PAYMENT, P.PRODUCT, P.DATE
FROM CUSTOMER C
LEFT OUTER JOIN MEMBERCARD M
ON M.MEMBERCARD = c.CUSTOMERID
LEFT OUTER JOIN PAYMENT P
ON P.CUSTOMERID = C.CUSTOMERID
ORDER BY C.CUSTOMERID
An OUTER JOIN is an optional join - if the data exists in the root table but doesn't exist in the joined table it will still be returned. Contrast this with an INNER JOIN (which is what you were doing, although you probably didn't realize it) where matching data must exist in both tables of the join for results to be returned.
Also, get in the habit of using ANSI-style joins as shown above, instead of the old-style implicit joins as used in your original query. It's easier to understand what's going on with ANSI joins.
Best of luck.

sql query help (count)

I have 3 tables
CUSTOMERS (CUSTOMER_ID, LASTNAME, FIRSTNAME, ... other fields)
LICENSES(LICENSE_ID, CREATED_AT, RELEASE_ID, CUSTOMER_ID, ... other fields)
RELEASES(RELEASE_ID, RELEASE_NAME, RELEASE_NUMBER, ... other fields)
CREATED_AT in LICENSE is a DATE (NOT NULL) field.
the tables are related according to primary key/foreign key with the same name; a customer can have 0 or more licenses and every license has a release.
I would like to get from these tables:
the customer's firstname, lastname and the release_id of the last license that was created (according to CREATED_AT field in LICENSE to find the last one ) if there is one.
for this one i used this query:
SELECT CUSTOMERS.FIRSTNAME,
CUSTOMERS.LASTNAME,
(SELECT RELEASES.RELEASE_ID
FROM RELEASES
INNER JOIN LICENSES ON LICENSES.RELEASE_ID = RELEASES.RELEASE_ID
INNER JOIN CUSTOMERS AS t ON t.CUSTOMER_ID = LICENSES.CUSTOMER_ID
WHERE t.CUSTOMER_ID = CUSTOMERS.CUSTOMER_ID
ORDER BY LICENSES.CREATED_AT DESC LIMIT 1) AS REL_ID
FROM CUSTOMERS
WHERE EXISTS
(SELECT 1
FROM RELEASES
INNER JOIN LICENSES ON LICENSES.RELEASE_ID = RELEASES.RELEASE_ID
INNER JOIN CUSTOMERS AS t ON LICENSES.CUSTOMER_ID = t.CUSTOMER_ID
AND t.CUSTOMER_ID = CUSTOMERS.CUSTOMER_ID)
It seems to work but I ask if someone can confirm me this or if it is possible to make it simpler.
The other data I want to get from these tables are RELEASES.RELEASE_ID, RELEASES.RELEASE_NAME, RELEASES.RELEASE_NUMBER and the count of customers who last license(according to CREATED_AT in LICENSES) has this release.
I was not able to create this query.
I am using h2 database.
Thanks for the help
This should probably be equivalent
SELECT CUSTOMERS.FIRSTNAME,
CUSTOMERS.LASTNAME,
(SELECT LICENSES.RELEASE_ID
FROM LICENSES
WHERE LICENSES.CUSTOMER_ID = CUSTOMERS.CUSTOMER_ID
ORDER BY LICENSES.CREATED_AT DESC
LIMIT 1) AS REL_ID
FROM CUSTOMERS
WHERE EXISTS (
SELECT 1
FROM LICENSES
WHERE LICENSES.CUSTOMER_ID = CUSTOMER.CUSTOMER_ID
)
You don't need to join all those tables if you have foreign key constraints on LICENSES.RELEASE_ID and LICENSES.CUSTOMER_ID. In particular, there's no point in joining the RELEASES table, because the LICENSES.RELEASE_ID column already contains the wanted information.
LATERAL / CROSS APPLY join in other databases
For completeness' sake, if this were PostgreSQL, Oracle, SQL Server, etc., you could perform a lateral join, which is also known as CROSS APPLY
SELECT CUSTOMERS.FIRSTNAME,
CUSTOMERS.LASTNAME,
l.RELEASE_ID
FROM CUSTOMERS
CROSS JOIN LATERAL (
SELECT *
FROM LICENSES
WHERE LICENSES.CUSTOMER_ID = CUSTOMERS.CUSTOMER_ID
ORDER BY LICENSES.CREATED_AT DESC
LIMIT 1
) l
How about this:
SELECT c.FIRSTNAME, c.LASTNAME, r.RELEASE_ID
FROM CUSTOMERS c
INNER JOIN LICENSES l ON (c.CUSTOMER_ID = l.CUSTOMER_ID)
INNER JOIN RELEASES r ON (r.RELEASE_ID = l.RELEASE_ID)
WHERE r.CREATED_AT = ( SELECT MAX(t.CREATED_AT) FROM RELEASES t
WHERE t.RELEASE_ID = r.RELEASE_ID )
because of the inner join, only customers with releases will be listed.

Two Inner Joins MYSQL

How would I preform two inner joins in one query?
Ie: three tables
Invoice
Address
Client
Invoice has a column which references an id in clients. It also has a column which references an address. I need to get both the clients name from the matched table and the address from the matched table. How would I INNER JOIN both tables?
I'll add a few details...
invoice has rows address(references address id), client(references client id), id and notes
client has rows first_name, last_name
address has rows street_name and city
I need to pull up
You can have as many JOIN clauses as you need in the query. Each has an ON clause where you specify the related columns between the joined tables.
SELECT
columns
FROM
invoice
INNER JOIN
address
ON
join_condition
INNER JOIN
client
ON
join_condition
Something like:
SELECT
c.*, i.*, a.*
FROM
invoices i
INNER JOIN
client c
ON
i.clientid = c.clientid
INNER JOIN
address a
ON
a.clientid = c.clientid
WHERE
i.id = 21
Don't forget you only select the fields you require, not * (all).
A sample e.g. based on learning from #Dan Grossman above:
SELECT FILM.TITLE, ACTOR.FIRST_NAME, ACTOR.LAST_NAME FROM ACTOR
INNER JOIN FILM_ACTOR
ON ACTOR.ACTOR_ID = FILM_ACTOR.ACTOR_ID
INNER JOIN FILM
ON FILM_ACTOR.FILM_ID = FILM.FILM_ID
WHERE ACTOR.FIRST_NAME = 'Nick' AND ACTOR.LAST_NAME = 'Wahlberg'

How to do a join with multiple conditions in the second joined table?

I have 2 tables. The first table is a list of customers.
The second table is a list of equipment that those customers own with another field with some data on that customer (customer issue). The problem is that for each customer, there may be multiple issues.
I need to do a join on these tables but only return results of customers having two of these issues.
The trouble is, if I do a join with OR, I get results including customers with only one of these issues.
If I do AND, I don't get any results because each row only includes one condition.
How can I do this in T-SQL 2008?
Unless I've misunderstood, I think you want something like this (if you're only interested in customers that have 2 specific issues):
SELECT c.*
FROM Customer c
INNER JOIN CustomerEquipment e1 ON c.CustomerId = e1.CustomerId AND e1.Issue = 'Issue 1'
INNER JOIN CustomerEquipment e2 ON c.CustomerId = e2.CustomerId AND e2.Issue = 'Issue 2'
Or, to find any customers that have multiple issues regardless of type:
;WITH Issues AS
(
SELECT CustomerId, COUNT(*)
FROM CustomerEquipment
GROUP BY CustomerId
HAVING COUNT(*) > 1
)
SELECT c.*
FROM Customer c
JOIN Issues i ON c.CustomerId = i.CustomerId
SELECT *
FROM customers as c
LEFT JOIN equipment as e
ON c.customer_id = e.customer_id --> what you are joining on
WHERE (
SELECT COUNT(*)
FROM equipment as e2
WHERE e2.customer.id = c.customer_id
) > 1
You can do it with a sub query instead of Joins:
select * from Customer C where (select Count(*) from Issue I where I.CustomerID = C.CustomerID) < 2
or whatever value you want

Performing select count across two tables sql

I have a table relationship which links one person to many relatives. so the tables are 1. Client. 2. Client_relative. I want to display all the rows of the Persons table, while displaying a count of how many relatives each person has. I have this query:
SELECT c.clientid, c.fname, c.lname, count(cr.relativeid) as relativecount FROM {client} AS c INNER JOIN {client_relative} cr on c.clientid = cr.clientid
This isn't working. Any ideas?
select c.*, cc.relativecount
from client c
inner join (
select clientid, count(*) as relativecount
from client_relative
group by clientid
) cc on c.clientid = cc.clientid