Given the following table transactions, which records the IDs of sellers and buyers who had a transaction, I would like to determine the user who was involved in the highest number of transactions and the number of transactions that user engaged in.
seller_id
buyer_id
date
1
4
2020-01-02
2
1
2020-01-03
3
2
2020-02-16
4
2
2020-02-22
4
3
2020-03-05
The desired output is this:
ID
n_trans
2
3
4
3
Because user 2 had a total of 3 transactions (1 as seller, 2 as buyer) and user 4 also had 3 transactions (2 as seller, 1 as buyer). It can be assumed that a user cannot be a buyer and seller in the same transaction, and that each buyer-seller combination is not duplicated.
What SQL query will get me this? I would not find any similar questions online. Thanks in advance!
You can unpivot, aggregate, and use window functions:
select id, cnt
from (select id, count(*) as cnt,
rank() over (order by count(*) desc) as seqnum
from ((select seller_id as id, date from t) union all
(select buyer_id, date from t)
) i
group by id
) i
where seqnum = 1;
Related
I have these 2 tables I am trying to write a query that will help me select all rows that gives this result
users
id
name
1
test
2
test2
logs
id
userId
message
date
1
1
this is a test
2020-10-07 12:57:14
2
1
another reason
2020-10-07 13:57:14
3
1
another reason 2
2020-10-07 14:57:14
4
2
another reason 3
2020-10-04 12:57:14
5
2
another reason 4
2020-10-05 12:57:14
6
2
another reason 4
2020-10-06 12:57:14
Output Table
I need to pass many user Ids like in this case (1,2) and get below table only return MAX (date) per row per userId
id
userId
message
date
3
1
another reason 2
2020-10-07 14:57:14
6
2
another reason 4
2020-10-06 12:57:14
Is this possible with one Query? This what I have but not working
SELECT
id ,
userId ,
message,
date
FROM logs
WHERE userId IN (1,2)
ORDER BY date DESC;
You may use the results of a window function ROW_NUMBER to retrieve these results.
SELECT
id,userId,message,date
FROM (
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY userId
ORDER BY date DESC
) as rn
FROM
logs
) t
WHERE rn=1 AND
userId IN (1,2)
ORDER BY date DESC
and for older mysql versions
SELECT
id,userId,message,date
FROM (
SELECT
l.*,
#row_num:=IF(userId=#prev_user_id,#row_num+1,1) as rn,
#prev_user_id:=userId
FROM
logs l
CROSS JOIN (
SELECT #row_num:=0, #prev_user_id:=NULL
) as vars
ORDER BY userId, date DESC
) t
WHERE rn=1 AND
userId IN (1,2)
ORDER BY date DESC
Find the top 2 accounts with the maximum number of unique patients on a monthly
basis.
Patient logs table
Account Id | date | Patient Id
1 2-1-2020 100
1 27-1-2020 200
2 1-1-2020 300
2 21-1-2020 400
2 21-1-2020 300
2 1-1-2020 500
3 20-1-2020 400
1 4-3-2020 500
sample output
Month |Account ID | no of unique patients
January 2 3
January 1 2
March 3 1
*Note: Prefer the Account Id with the least value in case of same number of unique patients
You can use window functions and aggregation:
select aym.*
from (select accountId, year(date) as yyyy, month(date) as mm,
count(distinct patient_id) as num_patients,
row_number() over (partition by year(date), month(date) order by count(distinct patient_id) as seqnum
from t
group by accountId, year(date), month(date)
) aym
where seqnum <= 2;
Date functions vary widely among databases. YEAR() and MONTH() are common functions; if your database doesn't support them, you should be able to find the right functions.
here is one way :
select * from (
select * , row_number() over (partition by month,AccountID order by count(distinct patienId) desc) rn
) t
where t.rn < 3
I have an SQL table that stores reports. Each row has a customer_id and a building_id and when I have the customer_id, I need to select the latest row (most recent create_date) for each building with that customer_id.
report_id customer_id building_id create_date
1 1 4 1553561789
2 2 5 1553561958
3 1 4 1553561999
4 2 5 1553562108
5 3 7 1553562755
6 3 8 1553570000
I would expect to get report id's 3, 4, 5 and 6 back.
How do I query this? I have tried a few sub-selects and group by and not gotten it to work.
If you are using MySQL 8+, then ROW_NUMBER is a good approach here:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY customer_id, building_id
ORDER BY create_date DESC) rn
FROM yourTable
)
SELECT
report_id,
customer_id,
building_id,
create_date
FROM cte
WHERE rn = 1;
If there could be more than one customer/building pair tied for the latest creation date, and you want to capture all ties, then replace ROW_NUMBER with RANK, and use the same query.
Another variation:
SELECT a.*
FROM myTable a
WHERE a.create_date = (SELECT MAX(create_date)
FROM myTable b
WHERE b.customer_id = a.customer_id
AND b.building_id = a.building_id)
Can try doing a search for "effective dated records" to see various approaches.
I have a table about metro card of station enter and record record(cid, enter_sid, exit_sid)
I want to get the total number of enter and out each station.
For example,
cid enter_sid exit_sid
1 1 2
1 1 2
1 2 3
2 2 1
I want to get
sid count(*)
1 3
2 4
3 1
I don't know how to combine select cid, count(*) from record group by enter_sid and select cid, count(*) from record group by exit_sid
cid means id of card.
For the first row of my expected outcome, 1 is for the id of station, 3 is for sid 1 existing 2 times in enter_sid and 1 time in exit_sid.
the trick to this is your enter and exit sid are the first column so you have to union those two together to get the correct combination... from there its a simple sum of the count.
SELECT sid, cid, SUM(counting) FROM
(
SELECT cid, enter_sid as sid, COUNT(*) as counting FROM record GROUP BY enter_sid
UNION ALL
SELECT cid, exit_sid as sid, COUNT(*) as counting FROM record GROUP BY exit_sid
)t
GROUP BY sid
Working Fiddle
Here is my tabel structure.
id
veh_id
user_id
amount
...
I have other tables to relate the user_id and veh_id as well.
I want to know how many times a user has put an amount on each veh_id and on how many occasions, this amount is actually the highest amount received. I would like to have those 2 counts for each user available.
id, veh_id, user_id, amount
1 1 30 100
2 1 32 105
3 2 30 100
4 2 32 95
5 2 33 90
I would like the select statement to give me:
user 30 as bid 2 times and 1 time is the higest bidder
user 32 as bid 2 time ans 1 time is the higest bidder
user 33 bid 1 time and 0 time the highest bidder
I don't know if it is possible to get those numbers.
This might be close, not sure exactly how you're relating vehicles together.
select
user_id,
count(*) as num_bids,
SUM(is_highest) as max_bids
from ( select
a.user_id,
COALESCE((select
MAX(b.amount) < a.amount
from bid as b
where b.id < a.id
and b.veh_id=a.veh_id
), 1) as is_highest
from bid as a
) as c
group by user_id
My understanding is user 30 has 2 max bids (2 first bids on a vehicle).
EDIT: If you're just looking for total 1 max bid per vehicle, let me know. That's actually a lot easier than rolling back to see who's bids were max when they came in...
EDIT2: Solution for only 1 max counts per vehicle:
Seems like this should be simpler for some reason:
select
user_id,
count(*) as num_bids,
count(vamt) as num_max
from bid
left join (
select veh_id as vid, max(amount) as vamt
from bid
group by veh_id
) as a on vid = veh_id and vamt <= amount
group by user_id
Try this,
select x.user_id, x.bid_times, COALESCE(y.max_times,0) as max_times from
(select user_id, count(*) as bid_times from testt group by user_id) as x
LEFT JOIN
(select user_id, count(*) as max_times from testt a where 0=( select count(*) from testt where amount > a.amount and veh_id=a.veh_id ) group by user_id) as y
ON x.user_id=y.user_id