I've a MySQL table where you have friends list.
+--------------+-------------+-------------+
| requester_id | accepter_id | accept_date |
+--------------+-------------+-------------+
| 1 | 2 | 2016-06-03 |
| 1 | 3 | 2016-06-08 |
| 2 | 3 | 2016-06-08 |
| 3 | 4 | 2016-06-09 |
| 1 | 5 | 2016-06-09 |
+--------------+-------------+-------------+
If there are multiple people with maximum number of friends (in this case 1 and 3 have 3 friends each), how can I print both 1 and 3 with their count.
I've the part where I can find the Nth largest person.
select s.requester_id, sum(s.total) as total_friends from (
select requester_id, count(accepter_id) as total from request_accepted
group by requester_id
union
select accepter_id, count(requester_id) as total from request_accepted
group by accepter_id
) as s
group by s.requester_id
order by total_friends desc;
I've managed to come up with this ugly but working code.
select s.requester_id, sum(s.total) as total_friends
from
(select requester_id, count(accepter_id) as total
from request_accepted
group by requester_id
union
select accepter_id, count(requester_id) as total
from request_accepted
group by accepter_id) as s
group by s.requester_id
having total_friends = (select max(s2.max_total)
from (select sum(s1.total) as max_total
from (select requester_id, count(accepter_id) as total
from request_accepted
group by requester_id
union
select accepter_id, count(requester_id) as total
from request_accepted
group by accepter_id) as s1
group by s1.requester_id) as s2)
Related
I Have two types of tractions tables where a user can be present in either one or both tables my Goal is to get a sum total for each user. the tables are as follows.
users
------------+----------+
| user_id | Name |
+-----------+----------+
| 1 | John |
------------+----------+
| 2 | Wells |
------------+----------+
shop1
------------+----------+--------------+
| trans_id | user_id | amount_spent |
+-----------+----------+--------------+
| 1 | 1 | 20.00 |
------------+----------+--------------+
| 2 | 1 | 10.00 |
------------+----------+--------------+
shop2
------------+----------+--------------+
| trans_id | user_id | amount_spent |
+-----------+----------+--------------+
| 1 | 2 | 20.05 |
------------+----------+--------------+
Expected Result after Summing
------------+-------------+
| user | Total Spent |
+-----------+-------------+
| John | 30.00 |
------------+-------------+
| Wells | 20.05 |
------------+-------------+
Use union all and group by:
select user_id, sum(amount_spent)
from ((select user_id, amount_spent from shop1) union all
(select user_id, amount_spent from shop2)
) s
group by user_id;
That said, you have a poor data model. In general, tables with the same columns are a very bad idea. You should have a single table for all shops with an additional column for the shop.
If you want the name, you need to join:
select u.name, sum(amount_spent)
from users u join
((select user_id, amount_spent from shop1) union all
(select user_id, amount_spent from shop2)
) s
using (user_id)
group by user_id, u.name;
You can use union all and aggregation:
select user_id, sum(amount_spent) total_spent
from (
select user_id, amount_spent from shop1
union all
select user_id, amount_spent from shop2
) t
group by user_id
select user_id, sum(amount_spent)
from
(shop1
UNION ALL
ship2)
group by user_id
I have a table like so (I'm not sure how to format tables)
Category / Products / Purchases
1 | A | 12
1 | B | 13
1 | C | 11
2 | A | 1
2 | B | 2
2 | C | 3
Expected output:
1 | B | 13
2 | C | 3
However I keep on getting
1 | A | 13
2 | A | 3
ie. It just selects the first occurrence of the second column.
Here is my code:
SELECT Category, Products, MAX(Purchases) FROM myTable GROUP BY Category;
Use filtering in the where clause:
select t.*
from t
where t.purchases = (select max(t2.purchases) from t t2 where t2.category = t.category);
With NOT EXISTS:
select m.* from myTable m
where not exists (
select 1 from myTable
where category = m.category and purchases > m.purchases
)
See the demo.
Results:
| Category | Products | Purchases |
| -------- | -------- | --------- |
| 1 | B | 13 |
| 2 | C | 3 |
You can use row_number() to identify max purchase for each group or replace rownumber() to rank() if there are ties of max purchases for each group
Select Category, Products,
Purchases from (Select Category,
Products,
Purchases,
row_number() over (partition by
category, products order by
purchases desc) rn from table) t
where t.rn=1
)
I have the following tables:
purchase_tbl
id | productId | purchaseQuantity
---+-----------+-----------------
1 | 1 | 30
2 | 2 | 30
3 | 1 | 10
4 | 2 | 10
sale_tbl
id | productId | saleQuantity
---+-----------+-------------
1 | 1 | 10
2 | 2 | 10
3 | 1 | 10
4 | 2 | 10
5 | 1 | 10
6 | 2 | 10
I need to get the output as this one:
productId | totalPurchasedQuantity| totalSaleQuantity
----------+-----------------------+------------------
1 | 40 | 30
2 | 40 | 30
I'm using this query and how to get the desired result?
SELECT purchase_tbl.productId
, SUM(purchase_tbl.purchaseQuantity) AS totalPurchaseQuantity
, SUM(sale_tbl.saleQuantity) AS totalSaleQuantity
FROM purchase_tbl
JOIN sale_tbl
ON purchase_tbl.productId = sale_tbl.productId
GROUP BY purchase_tbl.productId
Current output
productId | totalPurchaseQuantity | totalSaleQuantity
----------+-----------------------+------------------
1 | 120 | 60
2 | 120 | 60
You better group then in separate query, as table have multiple records for each product, which getting cross product.
SELECT purchase.productId, totalPurchaseQuantity, totalSaleQuantity
FROM
(SELECT purchase_tbl.productId
, SUM(purchase_tbl.purchaseQuantity) AS totalPurchaseQuantity
FROM purchase_tbl
GROUP BY purchase_tbl.productId) purchase
INNER JOIN
(SELECT sale_tbl.productId
, SUM(sale_tbl.saleQuantity) AS totalSaleQuantity
FROM sale_tbl
GROUP BY sale_tbl.productId
) sale ON sale.productId= purchase.productId;
To obtain your expected result you have to do the aggregation on the individual table before joining them. Your query with be like:
SELECT A.productId, A.totalpurchaseQuantity, B.totalsaleQuantity
FROM
(SELECT productId, SUM(purchaseQuantity)
totalpurchaseQuantity FROM purchase_tbl
GROUP BY productId) A JOIN
(SELECT productId, SUM(saleQuantity)
totalsaleQuantity FROM sale_tbl
GROUP BY productId) B ON
A.productId=B.productId;
I have the following table:
+----+-----------+-----------+
| id | teacherId | studentId |
+----+-----------+-----------+
| 1 | 1 | 4 |
| 2 | 1 | 2 |
| 3 | 1 | 1 |
| 4 | 1 | 3 |
| 5 | 2 | 2 |
| 6 | 2 | 1 |
| 7 | 2 | 3 |
| 8 | 3 | 9 |
| 9 | 3 | 6 |
| 10 | 1 | 6 |
+----+-----------+-----------+
I need a query to find two teacherId's with maximum number of common studentId's.
In this case teachers with teacherIds 1,2 have common students with studentIds 2, 1, 3, which is greater than 1,3 having common students 6.
Thanks in Advance!
[Edit]: After several hours I've had the following solution:
SELECT * FROM (
SELECT r1tid, r2tid, COUNT(r2tid) AS cnt
FROM (
SELECT r1.teacherId AS r1tid, r2.teacherId AS r2tid
FROM table r1
INNER JOIN table r2 ON r1.studentId=r2.studentId AND r1.teacherId!=r2.teacherId
ORDER BY r1tid
) t
GROUP BY r1tid, r2tid
ORDER BY cnt DESC
) t GROUP BY cnt ORDER BY cnt DESC LIMIT 1;
I was sure that there must exist more short and elegant solution, but I could not find it.
You would do this with a self-join. Assuming no duplicates in the table:
select t.teacherid, t2.teacherid, count(*) as NumStudentsInCommon
from table t join
table t2
on t.studentid = t2.studentid and
t.teacherid < t2.teacherid
group by t.teacherid, t2.teacherid
order by NumStudentsInCommon desc
limit 1;
If you had duplicates, you would just replace count(*) with count(distinct studentid), but count(distinct) requires a bit more work.
select t.teacherId, t2.teacherId, sum(t.studentId) as NumStudentsInCommon
from table1 t join
table1 t2
on t.studentId = t2.studentId and
t.teacherId < t2.teacherId
group by t.teacherId, t2.teacherId
order by NumStudentsInCommon desc
I have a very basic orders table:
+----------+---------+------------+---------+
| order_id | cust_id | order_date | book_id |
+----------+---------+------------+---------+
| 1 | 1 | 10/10/2014 | 1 |
+----------+---------+------------+---------+
| 2 | 1 | 10/10/2014 | 2 |
+----------+---------+------------+---------+
| 3 | 1 | 10/12/2014 | 1 |
+----------+---------+------------+---------+
| 4 | 2 | 10/18/2014 | 6 |
+----------+---------+------------+---------+
| 5 | 2 | 10/18/2014 | 77 |
+----------+---------+------------+---------+
| 6 | 2 | 10/18/2014 | 103 |
+----------+---------+------------+---------+
| 7 | 2 | 10/10/2014 | 13 |
+----------+---------+------------+---------+
| 8 | 3 | 10/09/2014 | 1 |
+----------+---------+------------+---------+
| 9 | 3 | 10/11/2014 | 2 |
+----------+---------+------------+---------+
| 10 | 3 | 10/12/2014 | 3 |
+----------+---------+------------+---------+
The query should:
- For each customer show order_date with Max number of orders. Example: customer 1 had 2 orders on 10/10/2014
- Special case: When customer has multiple days with most orders, show the earliest date. Example: customer 3 had 3 single item orders on different days. Need to show 10/09/2014.
I should be able to solve this without use of temp tables.
Kira
You need two clauses: 1) find the max number of orders per customer per day and 2) find the day on which the max number of orders occurred. The second step is needed to eliminate multiple days with same number of orders.
SELECT * FROM
(SELECT cust_id,
order_date,
count() cnt
FROM
orders
GROUP BY cust_id, order_date) x
JOIN
(SELECT cust_id,
MAX(cnt) max_cnt
FROM
(SELECT cust_id,
order_date,
count() AS cnt
FROM
orders
GROUP BY cust_id, order_date) n
GROUP BY cust_id) y
ON
y.max_cnt = x.cnt
AND
y.cust_id = x.cust_id
JOIN (SELECT x.cust_id,
min(x.order_date) AS dd
FROM
(SELECT cust_id,
order_date,
count() cnt
FROM orders
GROUP BY by cust_id, order_date) x
JOIN
(SELECT cust_id,
MAX(cnt) max_cnt
FROM
(SELECT cust_id,
order_date,
count() as cnt
FROM
orders
GROUP BY
cust_id, order_date) n
GROUP BY cust_id) y
ON
y.max_cnt = x.cnt
AND
y.cust_id = x.cust_id
GROUP BY cust_id) AS t2
ON
t2.cust_id=x.cust_id
AND
t2.dd=x.order_date;