I'm unable to join two tables without a duplicates in mysql - mysql

I have two tables:
Members (member_id, member_gender)
Orders (order_id, member_id, order_amount)
I have to retrieve data about the amount of members, amount of buyers (members with at least 1 order), amount of orders
But unfortunately I have a hard time because when i try to join these two tables i recieve dublicates and I am unable to count distinctive members
So my initial code was:SELECT count(m.member_id) AS Amount_of_members ,count(o.order_id) ,sum(o.order_amount) FROM tbl_member m LEFT JOIN tbl_order o ON m.member_id = o.member_id

You can ask the db to count only unique occurrences of the member id
SELECT count(DISTINCT m.member_id) AS Amount_of_members
You can also run a subquery to group the orders up so there is only one row per member before you join to the members table, which means the members data won't be doubled up if a member has 2 orders, tripled up if they have 3 etc
SELECT
count(m.member_id) AS Amount_of_members ,
sum(x.count_orders) as total_count_of_orders,
sum(x.sum_orders) as total_sum_of_orders
FROM
tbl_member m
LEFT JOIN (
SELECT
o.member_id,
count(o.order_id) as count_orders ,
sum(o.order_amount) as sum_orders
FROM
tbl_order o
GROUP BY o.member_id
)x ON m.member_id = x.member_id
Generally the "squash the many side of a 1:M relationship down to one row before the join is done" is a helpful way to manage the data, especially if there are multiple joins that need to be made. Getting everything 1:1 means no duplicates pop up

Related

mysql count rows from two tables in one query?

I have two MySQL-tables:
Persons (pid,name,companyID,companyName)
Orders (oid,companyID,details)
Now I want to count the number of order_id for each companyName as following:
Name Total
-------------------
CompanyName1 : 1200
CompanyName2 : 758
CompanyName3 : 11
I used this query but it's not working properly.
SELECT count(o.oid) as total,p.companyName
FROM orders as o, persons as p
WHERE o.companyID = p.companyID
GROUP BY p.companyName
Use join and group the result by p.companyID
SELECT p.companyName, count(o.oid) as total
FROM orders as o join persons as p
on o.companyID = p.companyID
GROUP BY p.companyID
If you are missing the companies without any orders you can use a left join.
SELECT p.companyName, count(*) as total
FROM persons p
LEFT JOIN orders o ON o.companyID = p.companyID
GROUP BY p.companyID, p.companyName
Please do not use the old, legacy join syntax any more - it is outdated since 1992.
Your data model looks messed up. That you have company ids and names in the person table but no corresponding companies table is highly suspicious.
In any case, presumably there can be multiple rows per company. You can condense the persons table and then join:
SELECT c.companyName, COUNT(*) as total
FROM orders o JOIN
(SELECT DISTINCT companyId, companyName
FROM persons p
) c
ON o.companyID = c.companyID
GROUP BY c.companyName;
However, you should fix the data model so you have a real bona fide companies table -- especially because you seem to care about that entity.

Select From multiple tables and relate with COUNT

first sorry, i don't have fluid english.
I want select 3 rows in 3 different tables, two of them without Foreing Key/relation.
Need to select amount of customers in each store, and total amount of payments in these stores in one query.
Here are the tables:
Customers
Stores
Payments
I have tried these querys to get payments for each store and customers for each store, but don't know how can unify in one query:
Payments/store
SELECT count(a.payment_id) as alquileres, b.store_id
FROM customer b, payment a
WHERE a.customer_id = b.customer_id
GROUP BY b.store_id;
customers/store
SELECT count(customer_id), store_id
FROM customer
GROUP BY store_id;
But when I add count(customer_id) in unique query don't have same results.
You can use one query:
select c.store_id,
count(distinct c.customer_id) as num_customers,
count(p.payment_id) as num_payments
from customers c left join
payments p
on p.customer_id = c.customer_id
group by c.store_id;

Counting amount of base records in (My)Sql 1-to-many relation

I have these two tables:
invoices (contains id field)
contracts (contains fk to invoice + 'code' field)
Let's say I have one record in the invoices table and two records in the contracts table. Both records in the contracts table point to the same invoice record.
Desire: I'd like to count the amount of invoices.
What I've got so far:
select
c.code, count(*)
from
invoices i
join
contracts c
on
c.invoice_id = i.id
group by
c.code
Although the count shows two instead of the desired 1. I understand that this is because of the join on the contract table, but not sure how to fix this.
Try with COUNT(DISTINCT i.id); it should count the different invoice id's in the resultset.
select
c.code, count(distinct i.id)
from
invoices i
join
contracts c
on
c.invoice_id = i.id
group by
c.code
You want the number of invoices?
select count(*)
from invoices i
You want invoices with contracts?
select count( distinct c.invoice_id)
from
contracts
Your code finds number of contracts per each invoice

Count group by across multiple tables

I am trying to get individual counts for multiple table join results.
I have a table of several divisions that should be joined to a table of dealers, which in turn, should be joined to a table of all the transactions by those dealers. I want to show how many dealer and transactions there are per division.
The following query returns the total number of transactions for both the transactionCount and the dealerCount, instead of unique values for each.
SELECT
d.*,
COUNT(dlr.id) AS dealerCount,
COUNT(t.id) AS transactionCount
FROM
division AS d
INNER JOIN
dealers AS dlr ON dlr.division = d.id
INNER JOIN
transactions AS t ON t.dealer_code = dlr.dealer_code
GROUP BY
d.id
I haven't tested this, but what about using
count(distinct dlr.id)
in your select?

Using a Combination of INNER and FULL OUTER Joins to Get Desired Data Set

I’ve got 5 Tables:
Patients Table 'PAT'
Patient Orders 'ORD'
Patient Comments 'Comm'
Patient Antigens 'Ant'
Patient MRNs 'MRN'
Information in the following four tables:
Pat has all of our patients information
Ord only has orders from the last four years, joined to the Pat table on Patient ID
Comm has all patient comments, joined on the Pat table on Patient ID
Ant has all antigens entered on patients, joined on the Pat table on Patient ID
MRN has all medical record numbers of patients, joined on the Pat table on Patient ID
What I’m trying to do it make sure I have all patients that appear in the Ord, Comm, Ant, and MRN tables and the join it to the Pat table to get information like first name, last name, sex, DOB...
So I’m trying to figure out how best to join these tables together to make sure I don’t include patients that don’t appear in the Ord, Comm, Ant, or MRN tables.
If I join the tables to my main patient table with left outer joins, I'll get all patients regardless if they have an order, comment, antigen, or MRN.
Select * from Pat
Left Outer Join Ord on Pat.X=Ord.X
Left Outer Join Comm on Pat.X=Comm.X
Left Outer Join Ant on Pat.X=Ant.X
Left Outer Join MRN on Pat.X=MRN.X
I've attempted to make a visual diagram of what I'm looking for:
My ideal query would return all Patients except for 4 and 10 because they do not have any orders, antigens, comments, or a MRN.
I was thinking I could perform FULL OUTER JOINS on the ORD, ANT, COMM, and MRN tables and then take those results and and join it to the PAT table.
Select *
FROM P50DATA.AGABFL1 ANT
FULL OUTER JOIN P50DATA.ORDMSTL1 ORD ON ANT.AGACCT=ORD.OPACCT
FULL OUTER JOIN P50DATA.DCMTRNL5 COMM ON ANT.AGACCT=COMM.DCACCT
FULL OUTER JOIN P50DATA.HOSPIDL1 HOS ON ANT.AGACCT=HOS.APACCT
But I don't know how to then take this data set and marry it to the Pat table so I could then get my patient information.
Thoughts?
This doesn't have to be too complicated.
ORD, ANT, COMM, and MRN don't have to join to each other, because you don't need the records in any one of them to match any other one. You just need to know whether they have records for a given patient or not.
There are many ways to construct such a query; here's one:
SELECT *
FROM PAT
WHERE EXISTS (
SELECT 1
FROM ORD
WHERE ORD.X = PAT.X
)
OR EXISTS (
SELECT 1
FROM ANT
WHERE ANT.X = PAT.X
)
OR EXISTS (
SELECT 1
FROM COMM
WHERE COMM.X = PAT.X
)
OR EXISTS (
SELECT 1
FROM MRN
WHERE MRN.X = PAT.X
)
Because you are querying the Patient table without joining it to anything, you don't have to worry about duplicate records, and because you're just checking existence for ORD, ANT, COMM, and MRN, you don't have to worry about exactly how many records each of them has for a given patient.