mysql select two tables with userid and compare timestamp and count it - php

Hello I think I try here something complicated. Maybe you can help me out here.
I have two tables: earnings and payouts.
Earnings has userid, amount, timestamp as datetime and other stuff. It has just information when user was earning something.
Example:
id | user_id | amount | timestamp |
1 | 2 | 1050 | 31days ago |
2 | 1 | 20 | 10days ago |
3 | 1 | 10 | 9 days ago |
4 | 2 | 10000 | 9 days ago |
...
Payouts has userid, amount, timestamp as datetime and has entries about payouts if a user is above x earnings lets say 1000. Example
id | user_id | payout_amount | timestamp |
1 | 2 | 1050 | 30days ago |
...
To my problem now. I want to COUNT how many payouts are NOT done (who has no entry in payout). This means. I need to compare payouts.timestamp with earnings.timestamp which has same userid and check if there are newer entries then the payouts. If yes then count it how many (so I think here its needed to sum first the earnings). I am not even sure if this is possible.
I can do it also with php if this isn't possible alone with mysql.
For example the result should be: count = 2 because userid 1 has just 30 earnings so he didn't reach the 1000 also he has no entry in payouts table. Userid 2 has 10000 but he still has no payouts because we didn't execute it or make a entry in the payouts table. he just has a old payout and the new earnings isn't paid.
Edit: the 10days ago things are just example. I use there real datetime types
EDIT2: Forget to say I tried this one:
select COUNT(e.amount) FROM earnings e, payouts p where p.payout_timestamp < e.timestamp AND p.user_id = e.user_id GROUP BY p.user_id, e.user_id
and go this:
| Count(e.amount) |
| 2 |
| 1 |

I think that comparing timestamps is not the only way to get result that you need. If these to tables correctly represent history of earnings and payments then you may just sum up total earnings and payments for each user and compare them counting every user_id that has less payments than earnings.
For example:
SELECT user_id, SUM(amount) as amount FROM earnings GROUP BY user_id;
sums up earnings for each user,
SELECT user_id, SUM(payout_amount) as amount FROM payouts GROUP BY user_id;
sums up payments for each user.
Now left join them and count users who has less payments than earnings:
SELECT COUNT(e1.user_id) FROM (SELECT user_id, SUM(amount) as amount FROM earnings GROUP BY user_id) as e1 LEFT JOIN (SELECT user_id, SUM(payout_amount) as amount FROM payouts GROUP BY user_id) as p1 ON e1.amount > p1.amount;
For your tables example my result was:
+-------------------+
| COUNT(e1.user_id) |
+-------------------+
| 2 |
+-------------------+
And to find users with payments not done just use the same query without COUNT() function:
+---------+
| user_id |
+---------+
| 2 |
| 1 |
+---------+
In my opinion this way is more stable because it is possible to have recent payments with less amount than total user earnings at the moment of payment, e.g.:
1) user earned 1000
2) then user earned 2000
3) and after that user been payed 1000
In this situation comparing timestamps without comparing amounts of payments will show you that this user has no payments to be done whereas you still need to pay him 2000.

Related

Connect two tables and count reservations per time slot

http://sqlfiddle.com/#!9/b729e5/1
In my reservation-system users should be able to sign up to multiple events at different time slots, each time slot has a limit of participants.
How can I connect these two tables in one MySQL-Query to get the number of places reserved per time slot of an event?
This data will be sent to php to show the user on a reservation page which time slot has free places and which is already booked up.
you may change the design of the reservations Table to be like this :
reservation_id | user_id | date_of_reservation | event_id | time_slot
then multiple reservations can be multiple rows for the same user ,
then link the two tables reservations and events using user_id + event_id
to test that your data is gethered correctly :
select r.user_id,r.event_id,r.time_slot,e.title
from reservations r,events e
where r.user_id = e.user_id
after that you can device your SQL easily using group by and count
select count(event_id)
from reservations r
where r.user_id = '<specific user>'
/*if you want*/
and time_slot between '' and ''
Fix your table structure first by adding another table like "EventTimeSlot".
Event -> id | host_id | date_of_event | title | description |
EventTimeSlot -> id | event_id | time_slot_name | max_participants |
Reservation -> id | user_id | date_of_reservation | event_id | time_slot_id |
Then make your question clear as I did not understand what you meant by "to get the number of places reserved per time slot of an event?".

How to select all entries of a user from a database?

I am trying to make a "top purchaser" module on my store and I am a bit confused about the MySQL query.
I have a table with all transactions and I need to select the person (which could have one or many transactions) with the highest amount of money spent in the past month.
What I have:
name | money spent
------------------
john | 50
mike | 12
john | 10
jane | 504
carl | 99
jane | 12
jane | 1
What I want to see:
With a query, I need to see:
name | money spent last month
-----------------------------
jane | 517
carl | 99
john | 60
mike | 12
How do I do that?
I do not really seem to find many good solutions since my MySQL query skills are quite basic. I thought of making a table in which money is added to the user when he buys something.
That's a simple aggregated query :
SELECT t.name, SUM(t.moneyspent) money_spent_last_month
FROM mytable t
GROUP BY t.name
ORDER BY t.money_spent_last_month DESC
LIMIT 1
The query sums the total money sped by customer name. The results are ordered by descending total money spent, and only the first row is retained.
If you are looking to filter data over last month, you need a column in the table that keeps track of the transaction date, say transaction_date, and then you can just add a WHERE clause to the query, like :
SELECT t.name, SUM(t.moneyspent) money_spent_last_month
FROM mytable t
WHERE
t.transaction_date >=
DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 2 MONTH)), INTERVAL 1 DAY)
AND t.transaction_date <=
DATE_SUB(NOW(), INTERVAL 1 MONTH)
GROUP BY t.name
ORDER BY t.money_spent_last_month DESC
LIMIT 1
This method is usually more efficient than using DATE_FORMAT to format dates as string and compare the results.

MySQL - Selecting the sum amount based on specific condition

I've searched for a few hours now, but couldn't find relative solution to a specific algorithm I am working on. To simplify the obstacle, I would like to present the information in just one table.
_____________________________________
| User | Item | price | qty |
-------------------------------------
| Annie | Dress | 80 | 1 |
| Bob | Jeans | 65 | 3 |
| Cathy | Shoes | 60 | 4 |
| David | Shirts | 40 | 6 |
| Annie | Shoes | 60 | 2 |
| Bob | Shirts | 55 | 2 |
| Cathy | Jeans | 65 | 1 |
| David | Ties | 20 | 5 |
-------------------------------------
Problem # 1: Show users whose total price for shopping at the store is 300 or more and quantity of their purchase is less than or equal to 3. These shoppers will be mailed a coupon for $40.
Problem # 2: Show users whose total qty is greater than or equal to 7 and the total for price is 275 or more. These shoppers will be mailed a coupon for $20.
The rows within the table are not transaction specific. The table can represent separate transactions within a month. We're just trying to find certain returning customers who we would like to reward for shopping with us.
I'm not sure if this can be done only via MySQL, or if I need to have separate queries and store rows into arrays and compare them one by one.
What I have tried so far are the followings:
SELECT * FROM table where SUM(price) as Total >= 300 AND SUM(qty) <=3;
I've also tried the following after the research:
SELECT SUM(price) as Total FROM table WHERE SUM(qty) <=3;
I keep getting syntax errors in MySQL shell. You don't have to solve the problems for me, but if you can guide me through the logic on how to solve the problems, I'd appreciate it very much.
Lastly I'd like to ask once, can I solve this with only MySQL or do I need to store the rows into PHP arrays and compare each indexes?
You can't use an aggregate function in the WHERE clause, you have to use HAVING. WHERE operates on individual rows during the selection, HAVING operates on the final results after aggregating.
SELECT *, SUM(price*qty) as Total
FROM table
GROUP BY user
HAVING Total >= 300 AND SUM(qty) <= 3
SUM is an aggregate function, meaning it applies to a group of clubbed rows. S say i am grouping the table data based on NAME then sum function would sum all the price of one NAME.
Having said this, if you think logically it would not make any sense to put the sum(price) in a WHERE clause because where clause would not know which SUM(PRICE) for which NAME to operate on(where clause operates only after a temporary view has been generated).
So we have the HAVING clause in SQL. This is used to compare the results of aggregrate function at each step of aggregation.
Consider it like this:
In where clause, when the ANNIE row from your DB is returned, it does not know what SUM(PRICE) means.
While in HAVING clause the SUM(PRICE)>300 condition is executed only when SQL has finished grouping all the ANNIE data into one group and calculated the SUM(PRICE) for her.
For question 1:
SELECT USER, SUM(PRICE)
FROM table
GROUP BY user
HAVING SUM(PRICE) >= 300 AND SUM(QTY) <= 3
For Question 2:
SELECT USER, SUM(PRICE)
FROM table
GROUP BY user
HAVING SUM(PRICE) >= 275AND SUM(QTY) >=7

mysql rank by column value grouped by column value

I am trying to figure out how to rank based on 2 different column numbers in laravel but raw mysql will do. I have a list of videos, these videos are inside of competitions and are given votes if someone likes the video. Each video will have a vote number and a competition number. I am trying to rank based on votes within competition. So for example below I have competition 8, I need the rank of all the videos in that competition based on votes. I then need the same for competition 5 etc.
|rank|votes|competition|
------------------
| 1 | 100 | 8 |
------------------
| 2 | 50 | 8 |
------------------
| 3 | 30 | 5 |
------------------
| 1 | 900 | 5 |
------------------
| 2 | 35 | 5 |
------------------
I have tried various group and selectby methods but nothing seems to work, any ideas?
In Mysql you can use user-defined variables to calculate rank,case statement checks if competition is same as the previous row then increment rank by one if different then assign 1 an order by is needed to have correct rank for the video
SELECT t.*,
#current_rank:= CASE WHEN #current_rank = competition
THEN #video_rank:=#video_rank +1
ELSE #video_rank:=1 END video_rank,
#current_rank:=competition
FROM t ,
(SELECT #video_rank:=0,#current_rank:=0) r
ORDER BY competition desc, votes desc
See Demo
If you are confused with the last extra column you can use a subselect
See Demo
You can use windowing functions:
select
competition, votes, rank() over (partition by competition order by votes desc) as rank
from
table1

Display data based on timeframe with SUM

With PHP and MySQL I am trying to display items with most votes over a certain period of time (24 hour, 1 week, 1 year, etc). When someone votes on an item, a table records the user, item id, vote, and time, like so:
Table1
username | itemid | vote | time
asdf | 127 | 1 | 1306726126
asdf | 124 | -1 | 1306726123
bob | 127 | 1 | 1306726129
bob | 124 | 1 | 1306726123
Now, I have another table with item details.
Table2
itemid | name | category | date | etc
What I WANT to do is call a table to display all the data from table 2 for only items with votes in the last 24hours and sort it by the votes. This means I need to SUM votes with TIME < 24 hours, then RIGHT JOIN (?) to my other database? I don't know, I am having difficulty figuring out how I should go about doing this. Any suggestiongs?
Something like this should work.
SELECT SUM(Table1.vote) as votes, Table2.* FROM Table2
LEFT JOIN Table1 ON Table1.itemid=Table2.itemid
WHERE Table1.`time`>=DATE_SUB(Table1.`time`, INTERVAL 24 HOUR)
GROUP BY Table1.itemid
ORDER BY Table1.votes DESC

Categories