how to count data buyer who had special condition mysql - mysql

i have data buyer the table called order_star_member, on this table contain createdAt. that row contain the date of transaction, users_id contain the buyer, and total_price_star_member was the amount of the transaction of each buyer, so i want to counting the amount of buyer who doing transaction >= 600000 in january and then doing transaction again in february 2020 for >= 600000 too, i tried to make insert new table for january itself and for february itself but it's just wasting time, do you know how exact syntax to solve this problem? i've tried this syntax but idk why the result was 0 instead when i check manual, the answer is 5 buyer who doing transaction in january for >= 600000 transaction and also in february >= 600000
select count(*) from (SELECT
b.users_id
FROM order_star_member b
WHERE
EXISTS (SELECT 1 FROM order_star_member d
WHERE d.users_id = b.users_id AND
d.createdAt >= '2019-12-01' AND d.createdAt < '2020-01-01') AND
EXISTS (SELECT 1 FROM order_star_member c
WHERE c.users_id = b.users_id AND
d.createdAt >= '2020-01-01' AND d.createdAt < '2020-02-01') AND
NOT EXISTS (SELECT 1 FROM order_star_member e
WHERE e.users_id = b.users_id AND d.createdAt < '2019-12-01') group by users_id having sum(total_price_star_member) >= 600000) inner_query;
sample data:
January
A (transaction 100000)
A (transaction 100000)
B (transaction 150000)
B (transaction 600000)
February
A (transaction 500000)
C (transaction 600000)
B (transaction 750000)
Expected Result after doing syntax
count of buyer who doing transaction >= 600000 in january and february : 1 (B buyer)

If you want users whose sum of the transactions exceeds 600,000 in each of January and February, then you can use two levels of aggregation:
select user_id
from (select osm.user_id, month(osm.createdAt) as mon,
sum(osm.price) as total_price
from order_star_member osm
where osm.createdAt >= '2020-01-01' and
osm.createdAt < '2020-03-01'
group by osm.user_id, month(osm.createdAt)
) um
where total_price >= 600000
group by user_id
having count(*) = 2;

The reason you are not getting 5 is the table alias references arent correct(replacing d with c and e)
select count(*) from
(SELECT b.users_id FROM order_star_member b WHERE
EXISTS (SELECT 1 FROM order_star_member d
WHERE d.users_id = b.users_id AND
d.createdAt >= '2019-12-01' AND
d.createdAt < '2020-01-01')
AND EXISTS (SELECT 1 FROM order_star_member c
WHERE c.users_id = b.users_id AND
c.createdAt >= '2020-01-01' AND
c.createdAt < '2020-02-01')
AND NOT EXISTS (SELECT 1 FROM order_star_member e
WHERE e.users_id = b.users_id AND
e.createdAt < '2019-12-01')
group by b.users_id having
sum(b.total_price_star_member) >= 600000) inner_query;
I would work on another group by level to deal with the grouping by month.

Related

Including and excluding specific records

I want to find some of buyer who had special condition (in this case, transaction >= 600000 called star member)
In this case, I want to find out star member (transaction >= 600000) who exists in January 2020 and March 2020, but it does not include star member who is doing transaction in February 2020.
here's my syntax
SELECT users_id
FROM order_star_member
GROUP BY users_id
HAVING SUM(CASE WHEN MONTHNAME(createdAt) = 'January'
THEN total_price_star_member END) >= 600000
AND SUM(CASE WHEN MONTHNAME(createdAt) = 'March'
THEN total_price_star_member END) >= 600000
AND NOT EXISTS (SELECT 1 FROM order_star_member
GROUP BY users_id
having sum(case when monthname(createdAt) = 'February'
THEN total_price_star_member END) >= 600000);
and here's my fiddle
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=2c85037215fe71f700b51c8fd3a5ae76
on my fiddle, the expected result are the users_Id 15 because that id order at january and march but not in february
First in the inner t we group by month to determine all the star members.
The outer grouping groups by user_id. Their score is the sum of their star_member.
For February (m=2 (February being the second month) on the first line of the query below) if they are a star_member, they get an penalty (-100) as an arbitrary value that the SUM cannot overcome.
The only way a month_score=2 can exist if if a user has a star_member being true (1) for both January and March but not February.
SELECT users_id, SUM(IF(m=2 and star_member, -100, star_member)) as month_score
FROM
(SELECT users_id,
MONTH(createdAt) as m,
SUM(total_price_star_member) >= 600000 as star_member
FROM order_star_member
WHERE createdAt BETWEEN '20190101' AND '20190331'
GROUP BY users_id, m
) t
GROUP BY users_id
HAVING month_score=2
fiddle

select mysql data with having sum

i have table order_star_member which contain users_id as the buyer, createdAt as the time the buyer doing transaction, and total_price_star_member as the amount of transaction, i want to find the buyer from january with the transaction >= 600000 and the buyer from january who also doing transaction >= 600000 (both of this month doing transaction >= 600000) idk what is the exact query, so i make a new table called january which contain the buyer who doing transaction in january >= 600000 and february which contain the buyer who doing transaction in february >= 600000, after that i use this syntax :
select count(*) as total from (SELECT
sum(b.total_price_star_member) as total_transaction, b.users_id
FROM order_star_member b
WHERE
EXISTS (SELECT 1 FROM january d
WHERE d.buyer_id = b.users_id) AND
EXISTS (SELECT 1 FROM february a
WHERE a.buyer_id = b.users_id) AND
NOT EXISTS (SELECT 1 FROM order_star_member c
WHERE c.users_id = b.users_id AND c.createdAt < '2020-01-01') group by b.users_id having sum(b.total_price_star_member) >= 600000 order by total_transaction) inner_query;
do you know what the exact query so i dont need to make new table again just like that.
example table
January 2020
users_id total_transaction
- 12 750000
- 13 450000
- 14 300000
february 2020
users_id total_transaction
- 12 650000
- 13 550000
- 14 650000
so when i run the query, then the users_id 12 will appear because in february and january he/she had a total transaction in >= 600000
SELECT users_id
FROM order_star_member
GROUP BY users_id
HAVING SUM(CASE WHEN MONTHNAME(createdAt) = 'January'
THEN total_price_star_member END) >= 600000
AND SUM(CASE WHEN MONTHNAME(createdAt) = 'February'
THEN total_price_star_member END) >= 600000;
fiddle

Identifying Duplicate Transactions in SQL

Recently because of an issue, multiple duplicate transactions were inserted into the database at different timings. Need to find those duplicate transactions and remove them.
I tried grouping the members and transactions
select count(*),
member_id,
TRUNC(created, 'DDD')
from TXN
where created > TO_DATE('06/01/2019 00:00:00', 'MM/DD/YYYY HH24:MI:SS')
group by member_id,
TRUNC(created, 'DDD')
having count(*) > 2;
I need all the transactions that were created in 10 minutes of time difference for the same member.
Examples:
MEMBER_ID ROW_ID ORG DEST Created
1-FRGD 1-FGTH YFG DFG 10-01-2019 00:00:00:00
1-FRGD 1-TYHG THU SEF 10-01-2019 00:00:09:12
1-FGHR 1-FTGH TGH DRF 10-01-2019 00:01:03:25
In this example, I need the first two txns as output because of not more than 10minutes if time difference and has the same member number
You may want self join:
select a.Member_Id as Member_Id,
a.Row_Id as Row_Id,
a.Org as Org,
a.Dest as Dest ,
a.Created as Created,
b.Row_Id as Duplicate_Row_Id,
b.Org as Duplicate_Org,
b.Dest as Duplicate_Dest,
b.Created as Duplicate_Created
from TXN a inner join
TXN b on a.Member_Id = b.Member_Id and
a.Created < b.Created and
TIMESTAMPDIFF(a.Created, b.Created) / 60 <= 10
order by a.Member_Id
For each record in TNX you provide its duplicate(s).
If you want to delete these transactions:
delete tnext
from txn tnext join
txn t
on tnext.member_id = t.member_id and
tnext.created > t.created and
tnext.created < t.created + interval 10 minute
where t.created > '2019-06-01';
Be sure you backup the table and test the logic using select before running this on your actual table.
If you simply want to select transactions without the duplicates, I would recommend not exists:
select t.*
from txn t
where not exists (select 1
from t tprev
where tprev.member_id = t.member_id and
tprev.created < t.created and
tprev.created > t.created - interval 10 minute
) and
t.created >= '2019-06-01';

MySQL , fetch persons by operation register_date

I have 2 tables..(MySQL)
PERSONS (person_id PRIMARY_KEY) and OPERATIONS(person_id FOREIGN_KEY).
I need to fetch person list where the period between each transaction is more than one year..
[![enter image description here][3]][3]
Example, Jessy'a transactions are
2012-12-25
TIMEDIFF(op1.REGISTER_DATE,op1.REGISTER_DATE) > 1 YEAR(OK)
2015-01-11
TIMEDIFF(op1.REGISTER_DATE,op1.REGISTER_DATE) < 1 YEAR
2015-09-11
TIMEDIFF(op1.REGISTER_DATE,op1.REGISTER_DATE) < 1 YEAR
2016-09-11
TIMEDIFF(op1.REGISTER_DATE,op1.REGISTER_DATE) < 1 YEAR
2016-01-11
TIMEDIFF(op1.REGISTER_DATE,op1.REGISTER_DATE) < 1 YEAR
2017-09-11
TIMEDIFF(op1.REGISTER_DATE,op1.REGISTER_DATE) < 1 YEAR
2017-08-11
TIMEDIFF(op1.REGISTER_DATE,op1.REGISTER_DATE) < 1 YEAR
2017-11-11
TIMEDIFF(op1.REGISTER_DATE,op1.REGISTER_DATE) < 1 YEAR
2017-01-11
if any TIMEDIFF > YEAR then add this person to my list , I need these persons..Please help..
I would do something like
select x from persons p
where not exists
(select o.id from operations o join operation o2
where o.person_id = p.id
and o2.person_id = p.id
and o.id != o2.id
and timediff(o.register_date, o2.register_date) < 1 year)
I just wanted to design the idea, timediff is something you have to look up, see how you can subtract timestamps and compare with time intervals.
in Oracle I try this...it's work..But in MySQL ?
SELECT PERSON_ID FROM
(
SELECT
op.PERSON_ID,
row_number() OVER (PARTITION BY op.PERSON_ID ORDER BY op.PERSON_ID) rownumber,
LEAD(op.REGISTER_DATE,1) over(PARTITION by op.PERSON_ID order by op.REGISTER_DATE),
MONTHS_BETWEEN(LEAD(op.REGISTER_DATE,1) over(PARTITION by op.PERSON_ID order by op.REGISTER_DATE),op.REGISTER_DATE)AS ferq
FROM operations op
)
WHERE ferq >= 12 AND rownumber = 1;

MySQL subquery returning multiple rows

SELECT CONCAT(MONTH(revenue_date),"/ ", YEAR(revenue_date)) as month_year,
(SELECT COUNT(DISTINCT DATE(delivery_date)) as operating_days
FROM table2 where weekday(delivery_date) <> 5 and
weekday(delivery_date) <> 6 and delivery_date < current_time and
year(delivery_date) > 2015 GROUP BY YEAR(delivery_date), MONTH(delivery_date)),
sum(revenue) as total_revenue,
from table1
where revenue_date < current_time and year(revenue_date) > 2015
group by year(revenue_date), month(revenue_date);
This shows the error "subquery returns more than 1 value". If I don't include group by in the subquery it returns just a total of all of the months but I need it to return it separately for all months.
Try this:
SELECT CONCAT(MONTH(revenue_date),"/ ", YEAR(revenue_date)) as month_year, a.operating_days
sum(revenue) as total_revenue,
from table2 JOIN
(SELECT YEAR(delivery_date) as `year`, MONTH(delivery_date) as `month`, COUNT(DISTINCT DATE(delivery_date)) as operating_days
FROM table2 where weekday(delivery_date) <> 5 and
weekday(delivery_date) <> 6 and delivery_date < current_time and
year(delivery_date) > 2015 GROUP BY YEAR(delivery_date), MONTH(delivery_date)) a
ON year(revenue_date) = a.year AND month(revenue_date) = a.month
where revenue_date < current_time and year(revenue_date) > 2015
group by year(revenue_date), month(revenue_date);
Join with the subquery.
SELECT DATE_FORMAT('%c/%Y', revenue_date) as month_year,
sum(revenue) as total_revenue, operating_days
from table1
JOIN (SELECT YEAR(delivery_date) AS delivery_year, MONTH(delivery_date) AS delivery_month,
COUNT(DISTINCT DATE(delivery_date)) as operating_days
FROM table2
where weekday(delivery_date) <> 5 and
weekday(delivery_date) <> 6 and delivery_date < current_time and
year(delivery_date) > 2015
GROUP BY delivery_year, delivery_month) AS t2
ON YEAR(revenue_date) = delivery_year AND MONTH(revenue_date) = delivery_month
where revenue_date < current_time
group by year(revenue_date), month(revenue_date);