Mysql Grouping and Counting - mysql

i have a 3 Tables:
1 TableTraders
trader_id|Domain|
---------------------
1|google.com
2|yahoo.com
2 Table Counter_in
counter_time counter_ip counter_domain_id
111111 222222 1
111111 222224 2
111111 222225 3
111111 222232 2
111111 222221 3
111111 222223 4
1111311 22223422 5
3 Table Out Counter
counter_time counter_ip counter_domain_id
111111 222222 1
111111 222222 2
111111 222222 3
111111 222226 2
111111 222221 3
111111 222222 4
1309351485 2130708581 5
1309351485 2130708581 4
1309710116 2130706433 4
1309351485 2130708581 1
1309710274 2130706433 1
Ok what i want todo is join the tables 1 , 2 , 3 and group them together, and count them.
trader_id|DOMAIN|IN|OUT
--------------------------
1|google.com|3|1
2|yahoo.com|1|2
I tried many things, but i get always wrong results. How do i join right the queries that i get results i want
*EDIT
The query attempted:
SELECT traders.trader_id, traders.domain, COUNT( counter_in.counter_domain_id ) AS today_in, COUNT( counter_out.counter_domain_id ) AS today_out
FROM traders
JOIN counter_in ON traders.trader_id = counter_in.counter_domain_id
JOIN counter_out ON traders.trader_id = counter_out.counter_domain_id
GROUP BY traders.trader_id, traders.domain
LIMIT 0 , 30
Results:
trader_id domain today_in today_out
1 bing.com 3 3
2 google.com 4 4
3 yahoo.com 4 4
4 msn.com 3 3
5 yandex.com 1 1

SELECT
TableTraders.trader_id,
TableTraders.Domain,
COUNT(TableIn.trader_id) AS in_count,
COUNT(TableOut.trader_id) AS out_count
FROM TableTraders
JOIN TableIn ON TableTraders.trader_id = TableIn.trader_id
JOIN TableOut ON TableTraders.trader_id = TableOut.trader_id
GROUP BY TableTraders.trader_id, TableTraders.Domain
Not certain what your table names are from your example above, since they contain spaces. Substitute the correct table names.

It appears the other answer may be giving you some sort of Cartesian result thus duplicating results. Take your traders and join to distinct sub-query counts from respective in / out tables.
SELECT
TT.trader_id,
TT.Domain,
TIN.InCount,
TOUT.OutCount
FROM
TableTraders TT
LEFT Join ( select Trader_ID, count(*) as InCount
from TableIn
group by Trader_ID ) TIN
on TT.Trader_ID = TIN.Trader_ID
LEFT Join ( select Trader_ID, count(*) as InCount
from TableOut
group by Trader_ID ) TOUT
on TT.Trader_ID = TOUT.Trader_ID
If you want it by DISTINCT IP address per in/out, just change
COUNT(*)
to
COUNT( Distinct IP )

Related

how count and sum records in three tables using mysql phpmyadmin?

I m new to this community and also new to MySQL.
Need to COUNT the clients and SUM the commission for each referrer respectively using MySQL query.
referrer table
id
referrer_name
1
referre1
2
referre2
3
referre3
4
referre4
client table
id
referrer_id
client_name
1
1
client1
2
1
client2
3
2
client3
4
3
client4
5
4
client5
commission table
id
client_id
commission
1
1
20
2
1
32
3
3
24
4
4
15
I want to achieve below output using above 3 tables.
referrer_id
referrer_name
total_client
total_commission
1
referre1
2
52
2
referre2
1
24
3
referre3
1
15
4
referre4
1
0
I have tried the following query
SELECT referrer.referrer_name as name,
(SELECT COUNT(*) FROM client WHERE client.referrer_id=referrer.id) as total_client,
(SELECT SUM(commission) FROM commission WHERE commission.client_id=client.id) as total_commission FROM referrer LEFT JOIN client ON client.referrer_id=referrer.id GROUP BY name;
Read Mysql join and Aggregate Functions
SELECT t2.referrer_id,
t1.referrer_name,
COUNT(DISTINCT t2.id) AS total_client,
SUM(t3.commission) AS total_commission
FROM referrer t1
JOIN client t2 ON t1.id = t2.referrer_id
JOIN commission t3 ON t2.id = t3.client_id
GROUP BY t1.referrer_id

Trying to get latest status for related shipment but the results I receive are incorrect

I am currently working on a project while trying to learn MySQL and I would like to join three tables and get the latest status for each related shipment. Here are the tables I'm working with (with example data):
shipments
id
consignee
tracking_number
shipper
weight
import_no
1
JOHN BROWN
TBA99900000121
AMAZON
1
101
2
HELEN SMITH
TBA99900000190
AMAZON
1
102
3
JACK BLACK
TBA99900000123
AMAZON
1
103
4
JOE BROWM
TBA99900000812
AMAZON
1
104
5
JULIA KERR
TBA99900000904
AMAZON
1
105
statuses
id
name
slug
1
At Warehouse
at_warehouse
2
Ready For Pickup
ready_for_pickup
3
Delivered
delivered
shipment_status (pivot table)
id
shipment_id
status_id
1
1
1
2
2
1
3
3
1
4
4
1
5
5
1
6
1
2
7
2
2
8
3
2
9
4
2
10
5
2
all tables do have created_at and updated_at timestamp columns
Example of the results I'm trying to achieve
slug
shipment_id
status_id
ready_for_pickup
1
2
ready_for_pickup
2
2
ready_for_pickup
3
2
ready_for_pickup
4
2
ready_for_pickup
5
2
Here's the query I wrote to try to achieve what I'm looking for based on examples and research I did during the past couple of days. I find that sometimes there is sometimes a mismatch with the latest status that relates to the shipment
SELECT
statuses.slug AS slug,
MAX(shipments.id) AS shipment_id,
statuses.id AS status_id,
FROM
`shipments`
INNER JOIN `shipment_status` ON `shipment_status`.`shipment_id` = `shipments`.`id`
INNER JOIN `statuses` ON `shipment_status`.`status_id` = `statuses`.`id`
GROUP BY
`shipment_id`
Because we need to reference other fields from the same record that evaluates from the MAX aggregation, you need to do it in two steps, there are other ways, but I find this syntax simpler:
SELECT
shipments.id AS id,
statuses.slug AS slug,
statuses.id AS status_id,
shipment_status.shipment_id as shipment_id
FROM
`shipments`
INNER JOIN `shipment_status` ON `shipment_status`.`shipment_id` = `shipments`.`id`
INNER JOIN `statuses` ON `shipment_status`.`status_id` = `statuses`.`id`
WHERE
shipment_status.id = (
SELECT MAX(shipment_status.id)
FROM `shipment_status`
WHERE shipment_status.shipment_id = shipments.id
)
try it out!
This query makes the assumption that the id field is an identity column, so the MAX(shipment_status.id) represents only the most recent status for the given shipment_id
You can use window functions:
SELECT s.id, st.slug, st.id
FROM shipments s JOIN
(SELECT ss.*,
ROW_NUMBER() OVER (PARTITION BY shipment_id ORDER BY ss.id DESC) as seqnum
FROM shipment_status ss
) ss
ON ss.shipment_id = s.id JOIN
statuses st
ON ss.status_id` = st.id
WHERE ss.seqnum = 1;
Also note the use of table aliases so the query is easier to write and to read.

Get most recent groups ordered by users last login date DESC

The title makes it sound easy but what I'd like to do is get the last 20 groups from the groups table, ordered by their corresponding users last login date. A group can have one or more users and ultimately what I want to do is find out which groups have had the least user activity and retrieve the last login date.
Here's the query I came up with -
SELECT DISTINCT g.name, user_max.max_login_last_at FROM groups g
LEFT JOIN group_user gu on g.id = gu.group_id
LEFT JOIN (
SELECT MAX(login_last_at) max_login_last_at, u.id
FROM users u GROUP BY id
) AS user_max ON (user_max.id = gu.user_id)
ORDER BY user_max.max_login_last_at ASC
The problem is when I perform the join, it pulls in every group_user record and results in duplicates. I feel like there could be an easy solution to this one but I can't seem to figure it out!
groups table
id name
1 Group 1
2 Group 2
users table
id email login_last_at
1 user1#example.com 2018-10-17 16:08:47
2 user2#example.com 2018-10-02 15:41:53
3 user3#example.com NULL
4 user4#example.com 2018-10-08 12:01:48
5 user5#example.com 2018-10-15 9:24:57
6 user6#example.com 2018-10-17 11:10:58
7 user7#example.com 2018-10-17 15:33:03
group_user table
id group_id user_id
1 1 1
2 2 1
3 1 2
4 1 3
5 1 4
6 2 5
7 1 5
8 2 6
9 1 7
Current example result -
name max_login_last_ts
Group 1 2018-10-02 15:41:53
Group 1 2018-10-08 12:01:48
Group 2 2018-10-15 09:24:57
Group 1 2018-10-15 09:24:57
Group 2 2018-10-17 11:10:58
Group 1 2018-10-17 15:33:03
Group 1 2018-10-17 16:08:47
Group 2 2018-10-17 16:08:47
Group 1 2018-10-18 08:55:17
The problem is as you can see in the result above is that I'm getting all groups, all I really want is the following -
name max_login_last_ts
Group 2 2018-10-17 16:08:47
Group 1 2018-10-18 08:55:17
Thanks in advance!
I think this query will do what you want. There isn't enough data in your sample to replicate your desired results though.
SELECT g.name, MAX(u.login_last_at) AS max_login_last_at
FROM `groups` g
JOIN group_user gu on gu.group_id = g.id
JOIN users u ON u.id = gu.user_id
GROUP BY g.name
ORDER By max_login_last_at DESC
LIMIT 20
Demo on dbfiddle

How to write mysql query for fetching data from 2 sql query?

I have 2 tables
tbltraining
trId(PK) trname
------- ------
1 training1
2 training2
3 training3
4 training4
5 training5
6 training6
tbltrainAssign
trassigno trId(FK) date1 date2
--------- ------ ----------- ----------
1 1 12/12/2012 12/12/2013
1 1 12/12/2012 12/12/2013
2 3 01/12/2012 08/12/2013
2 3 01/12/2012 08/12/2013
2 3 01/12/2012 08/12/2013
3 1 02/12/2012 12/12/2013
3 1 12/12/2012 12/12/2013
what i want is the data from tbltraining with the count of assignments. trId =1 is assigned 2 times and trId is assigned 1tim in tbltrainAssign . so the result should look like
trId trName count
1 training1 2
2 training2 0
3 training3 1
4 training4 0
5 training5 0
6 training6 0
What you need is a simple, straightforward, JOIN especially LEFT JOIN to get unmatched trNames that had no assignment in the second table, with COUNT and a GROUP BY like so:
SELECT t.trId, t.trname, COUNT(s.trId)
FROM tbltraining t
LEFT JOIN tbltrainAssign s ON t.trId = s.trId
GROUP BY t.trId, t.trname;
SQL Fiddle Demo
Side not: Please avoid descriptive prefixes that you are using in the tables' names and the columns' names the tbl and the tr.
Update: You have to select the distinct dates from the assignment table in order to count the distinct assignments for each training like so:
SELECT t.trId, t.trname, COUNT(s.trId)
FROM tbltraining t
LEFT JOIN
(
SELECT DISTINCT trId, DATE(date1), date(date2)
FROM tbltrainAssign
) s ON t.trId = s.trId
GROUP BY t.trId, t.trname;
Updated SQL Fiddle Demo
select a.trId trId,a.trName trName,count(distinct b.trssigno) count
from tbltraining a, tbltrainAssign b
where a.trId=b.trId
group trId,trName
order by trId
this will give the desired result
select t.trId, t.trname, count(t.trassigno) from (
select tb.trId, tb.trname, ta.trassigno from tbltrainAssign ta
inner join tbltraining tb on ta.trId=tb.trId
) t
group by t.trId, t.trname

MYSQL select query using count (*)

i have a problem concerning a select query in MYSQL
i have two different tables and i want to obtain a certain result
i used COUNT method which gave me only the results (>=1)
But in reality , i want to use all counts with zero included how to do it?
My query is:
SELECT
first.subscriber_id,
second.tag_id,
COUNT(*)
FROM
content_hits first
JOIN content_tag second ON first.content_id=second.content_id
GROUP BY
second.Tag_id,first.Subscriber_id<br>
First table:Content_hits
CONTENT_ID SUBSCRIBER_ID
30 1
10 10
34 4
32 2
40 3
28 3
30 6
31 8
12 3
Second table:Content_tag
CONTENT_ID TAG_ID
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
10 1
11 2
12 2
13 2
14 2
Result but incomplete For example:Subsrciber6 for tag_id=1 should have a count(*)=0
subscriber_id tag_id COUNT(*)
1 1 4
2 1 7
3 1 2
4 1 1
5 1 3
7 1 2
8 1 1
9 1 1
10 1 3
1 2 2
2 2 3
3 2 2
Now that you have further elaborated on what you actually want to achieve, it can be seen that the problem is much more complex. You actually want all combinations of subscriber_id and tag_id, and then count the number of actual entries in the joined table product. whew. So here goes the SQL:
SELECT combinations.tag_id,
combinations.subscriber_id,
-- correlated subquery to count the actual hits by tag/subscriber when joining
-- the two tables using content_id
(SELECT count(*)
FROM content_hits AS h
JOIN content_tag AS t ON h.content_id = t.content_id
WHERE h.subscriber_id = combinations.subscriber_id
AND t.tag_id = combinations.tag_id) as cnt
-- Create all combinations of tag/subscribers first, before counting anything
-- This will be necessary to have "zero-counts" for any combination of
-- tag/subscriber
FROM (
SELECT DISTINCT tag_id, subscriber_id
FROM content_tag
CROSS JOIN content_hits
) AS combinations
Not sure, but is this what you want?
SELECT first.subscriber_id, second.tag_id, COUNT(*) AS c
FROM content_hits first JOIN content_tag second ON first.content_id=second.content_id
GROUP BY second.Tag_id,first.Subscriber_id HAVING c = 0