MySQL Two Table Query Count - mysql

I have two tables A & B.
Table A
GROUP # | GROUP NAME
1 group a
2 group b
3 group c
Table B will have a column with group # and then a bunch of other data.
I'm trying to figure out how I can create a query that will return the GROUP NAME from TABLE A and the number of rows associated with each group name from TABLE B.
Essentially I'm trying to get the following output:
GROUP NAME | COUNT
group a x
group b y
group c z
I've been trying variations of the following to no avail...
SELECT DISTINCT "GROUP NAME", COUNT(*) from A, B where A.GROUPNUM = B.GROUPNUM;

You will need to apply the aggregate COUNT() over the group GROUP NAME (using GROUP BY) to get the count you are looking for. DISTINCT doesn't come into play in this instance,
Note that a column name with spaces will need to be quoted using backticks, not single or double quotes. I'm also replacing your implicit join with an explicit INNER JOIN, which is the modern preferred syntax.
SELECT
`GROUP NAME`,
COUNT(B.GROUPNUM)
FROM
A
INNER JOIN B ON A.GROUPNUM = B.GROUPNUM
GROUP BY `GROUP NAME`
Here's a little demonstration: http://sqlfiddle.com/#!2/2123f/2

Try the below, note that you will want to use a left join (like below) if you also want to show group names on table a that have no rows on table b.
select a.group_name, count(b.groupnum)
from a
left join b
on a.groupnum = b.groupnum
group by a.group_name

Related

mysql understanding group by with a joined table

So I have the "main" table (A) with fields: id, order_number, order_name and table (B) with fields: id, fk.order_number, tracking_number
Table (A) is responsible for keeping track of each order, while table (B) stores all associated tracking information per each order.
What I am trying to accomplish is to query each order from table A and join table B to show the first tracking number that has been stored for each order, almost like a limit 1 (return only the first stored tracking number for each order).
How I am doing this currently is a join between table A and table B on the order_number field, but I am using the GROUP BY tableA.order_number at the end of the statement.
select tablea.order_number, tablea.order_name, tableb.tracking_number
from tablea
join table b
on tablea.order_number = tableb.order_number
group by tablea.order_number
I guess the question revolves around, what is the default group by ordering when you return multiple rows back from the joined table?
For example, in table A, there is only 1 row, while in tale B there are 2 rows (2 tracking numbers for the order). So, when I group by in this case, does that always take the first match from the joined table where the condition matches the group by? If I removed group by, 2 rows would be returned.
I realize what is happening because I have the group by condition on tableA, and so it only shows the first row because both rows returned from the join have the same order number, which appears to be what I want (limit 1 tracking number per order), but I'm not sure if programmatically I actually did this correctly or if it happens this way because that is how the group by clause works and how I used it here. I just want to limit 1 tracking number from the tableB based on the order_number of table A.
Updated (with example query)
SELECT m.message_id, m.message_date, m.message_order_number, m.message_purchase_order, m.message_vendor_invoice, ve.vendor_email_display, concat(c.customer_first_name, ' ', c.customer_last_name) as customer_name,
min(ti.tracking_information_id) as tracking_information_id, ti.tracking_information_tracking_number, ti.tracking_information_tracking_number_status
FROM email.message m
JOIN email.customer c
ON m.message_tagged_customer_first = c.customer_id and m.message_tagged_customer_last = c.customer_id
JOIN vendor_email ve
ON m.message_sender = ve.vendor_email_id
LEFT JOIN tracking_information ti
ON m.message_order_number = ti.tracking_information_order_number
group by m.message_order_number
In this case, I want to return all information in message table, and the first matching row in table tracking
Group byis for aggregation function as MIN() ,, MAX() , COUNT() . .. and is for define respect which column the aggreagtion function must be performed..
If you are looking for a specific ordered result you should use ORDER BY that work for the columns value as is
select tablea.order_number, tablea.order_name, tableb.tracking_number
from tablea
join table b on tablea.order_number = tableb.order_number
order by tablea.order_number

SQL query regarding nested query topic

Query that displays all "Father (Husband)" names in alphabetical order from Guardian table with total number of their "Wives" (use nested query to find count of wives).
enter image description here
You could use a self join and group by
select a.guardianName as husband_name, count(*) as count_of_wives
from my_table a
left join my_table b on b.husband_id = a.guardianId
where a.husband_id is null
group by a.guardianName

Get a row which has the maximum id

Problem in simple words, 1st must be left joined to the 2nd table where the record is latest. So, I use an approach of using function MAX()
Currently I have 2 tables.
matches
matches_payments
|
Now I want to join the second table to first one using MAX(id) on matches_payments
Desired result
but I am not getting desired result due to greatest-n-per-group problem.
Query
SELECT matches.id, mp.*
FROM matches
LEFT JOIN (SELECT
MAX(id) AS id,
match_id
paymentStatus
FROM matches_payments
GROUP BY match_id) AS mp ON mp.id = matches.id;
Desired result is not produced due to : Stackoverflow Question
When using this feature, all rows in each group should have the same values for the columns that are ommitted from the GROUP BY part. The server is free to return any value from the group, so the results are indeterminate unless all values are the same.
FROM MySQL Dev
PS : I know the tables are poorly designed. It is not my work as the last developer did those.
You need two joins. You need a self-join of the matches_payments table to get the row with the highest ID for each match_id, as shown in SQL Select only rows with Max Value on a Column. Then you LEFT JOIN this to matches to combine the two tables:
SELECT m.*, mp.paymentStatus, mp.paymentAmount
FROM matches AS m
LEFT JOIN (
SELECT mp1.*
FROM matches_payments AS mp1
JOIN (SELECT match_id, MAX(id) AS id
FROM matches_payments
GROUP BY match_id) AS mp2
ON mp1.match_id = mp2.match_id AND mp1.id = mp2.id
) AS mp ON mp.match_id = m.id

Select * but group by a certain column, only for a certain column

Here is my table structure
Company table
|id|name|company_id
Images table
|id|file|type|company_id
Now, I am trying to group by type from images, it can have 2 types (logo|banner), but if I use group by type that will do it for all the rows, not just where the id = company id
My query so far:
SELECT * FROM companies c
LEFT JOIN images i
ON i.comp_id = c.id
As mentioned above if I do the following
SELECT * FROM companies c
LEFT JOIN images i
ON i.comp_id = c.id
group by type
It will group ALL rows (as you would expect), so how can I group by type and only where the company_id (from images) is the same?
You can group by multiple fields:
GROUP BY `type`, `company_id`
Sidenote: using GROUP BY without any aggregate functions is usually a mistake, and most RDBMS will not let you GROUP BY without specifying all non-aggregated fields; but am I correct assuming you are working your way towards that?

group by but still displaying all data?

i wonder how to using group by but still displaying full data? i just want to group it.
here i give an example of my table :
this is my query :
(SELECT dp.menu_paket,d.id_detail,t.no_meja,m.nama_menu,d.jumlah,t.status,t.nama_pegawai
FROM menu m
join detail_paket dp on dp.menu_paket=m.nama_menu
JOIN detail_transaksi d on m.id_menu = d.id_menu
join transaksi t on t.id_transaksi=d.id_transaksi where t.status='progress' and d.status_menu='progress' group by id_detail)
UNION
(SELECT dp.menu_paket,d.id_detail,t.no_meja,p.nama_paket,d.jumlah,t.status,t.nama_pegawai
FROM paket p
join detail_paket dp on dp.id_paket=p.id_paket
JOIN detail_transaksi d on d.id_paket=p.id_paket
join transaksi t on t.id_transaksi=d.id_transaksi where t.status='progress' and d.status_menu='progress' group by id_detail);
thanks..!
You can apply distinct to avoid same multiple records instead of group by. because group by is used when there is aggregate function is your query.
Distinct retrieves single row instead of multiple rows when two rows are totally same.
Try this
select distinct columnname from table name
union
select distinct columnname1 from table name
I think I see two issues.
1) GROUP BY is generally used when you want to group rows for an aggregate function like SUM. You may be looking for ORDER BY, which controls the order of the rows. You can specify multiple columns for ORDER BY to obtain a "grouping" effect. This is what you want if you just want the rows to be next to each other in the list.
2) UNION, at least in the databases I know of, removes duplicate rows. You want UNION ALL if you want to preserve all rows.
Edit:
In response to the poster's comment, you definitely want ORDER BY and maybe UNION ALL. It should be ORDER BY no_meja, id_transaksi. Try the following query and see if it gives you what you want:
SELECT * FROM
((SELECT dp.menu_paket,d.id_detail,t.no_meja,m.nama_menu,d.jumlah,t.status,t.nama_pegawai
FROM menu m
join detail_paket dp on dp.menu_paket=m.nama_menu
JOIN detail_transaksi d on m.id_menu = d.id_menu
join transaksi t on t.id_transaksi=d.id_transaksi
where t.status='progress' and d.status_menu='progress')
UNION ALL
(SELECT dp.menu_paket,d.id_detail,t.no_meja,p.nama_paket,d.jumlah,t.status,t.nama_pegawai
FROM paket p
join detail_paket dp on dp.id_paket=p.id_paket
JOIN detail_transaksi d on d.id_paket=p.id_paket
join transaksi t on t.id_transaksi=d.id_transaksi
where t.status='progress' and d.status_menu='progress')) x
ORDER BY x.no_meja, x.id_transaksi;