How to update another row's column after update on a column - php

As the title says I want to automatically update another row's column after an update on a specific column.
I have this table
id username direct_referral indirect_referral total_referral referrer_id paid
---------------------------------------------------------------------------------
1 aj 100 56 156 1 1
2 john 100 40 140 1 1
3 michael 100 0 100 2 1
Now in this table refferer_id = id of referrer. For example aj has referred 'john' so he get 40% of the total_referral of john i.e.(140*40/100 = 56). john has referred michael so his indirect_referral will be 40% of michael i.e. (100*40/100 = 40).
Now I want to automatically increase indirect_referral of referrer by 40% of the total_referral of referral whenever a new user joins through his referral id and paid = 1.
Please tell me how can I do this process automatically and thanks in advance.

Your problem is tricky. But it might be solvable by a recursive SQL statement, also called CTE (common table expression).
There you have one initial query as an anchor member (the row you want to insert) and a recursive query that calls itself again and again.
Look at that link for an deeper explanation: https://www.mysqltutorial.org/mysql-recursive-cte/
Another way of solving your problem is to make a lot of SQL queries, that you manage by your PHP code.

Related

PHP coders suggestions on alternative to WHERE NOT IN query

I am trying to build a simple randomised voting system for a site, currently, and I believe wrongly, I have the following setup
as the user goes to the random voting section of the site, he is presented with a votable item that firstly, is an item that was last voted on the longest time agp, Secondly, isn't something the user voted for before and thirdly must be relevant to them based upon their list of relevant subjects. As a side note, if the user skips the vote, it can't show them the same thing again later in the list and all the single votes must be recorded to produce statistics.
Currently, the way I am doing this is by holding a serialized array against their account in the database containing a list of vote item Id numbers that they have previously voted for.
I would like to say at this point that I don't condone this, and inserting a serialized array into the database was silly, and I regret my actions ;) .
Nevertheless, I couldn't figure out another way to do this. at this point, the array is built upon by users voting which adds to the list. but the query would become massive if I was to continue and someone had up to 100 things they could vote for. At this point I am using this query to get the next item in the list:
//$finarr is the received unserialized list of values from the database
$sql = "SELECT * FROM vote_item_headers WHERE Id NOT IN (".$finarr.") ORDER BY LastVoted DESC LIMIT 1"
//execute query and display results
I should also note that at this point, I haven't even bothered adding in the third requirement above because frankly, I didn't even know where to begin or anything when I had to make a query that needed to encompass all of the requirements above.
A bit more information you might find relevant:
I have some other tables which are explained below.
core_users = list of users and their interests
core_interests = a list of all interests
core_language = a list of the different possible languages that an item could fall into
vote_item_headers = a list of all the votable items with a reference in the interests and lang tables to define extra properties of the votable item.
core_votes = the master list of people's votes
I am really sorry if this is too vague for you guys, all I really want is guidance in this instance when dealing with large amounts of information that needs to be combined to get a result.
Any suggestions welcome. I am happy to restructure the entire thing just to get it right.
voted
user_id | Id
----------+------
1 | 12
1 | 14
1 | 187
2 | 23
SELECT * FROM vote_item_headers
WHERE Id NOT IN (
SELECT Id FROM voted WHERE user_id=1234
)
ORDER BY LastVoted DESC LIMIT 1
but you also want relevant posts
relevant_posts
user_id | Id
----------+------
1 | 342
1 | 253
1 | 32
2 | 53
SELECT vote_item_headers.* FROM vote_item_headers
# cut down the amount returned with relevant_posts table
INNER JOIN relevant_posts ON (
vote_item_headers.Id=relevant_posts.Id
AND user_id=1234
)
WHERE vote_item_headers.Id NOT IN (
SELECT Id FROM voted WHERE user_id=1234
)
ORDER BY LastVoted DESC LIMIT 1

Handling numerical lists in php and MySQL

I'm writing a small list system which is ordered via a numerical field in the database that is dynamic
The database holds the following:
Id | position | person
======================
1 | 3 | John
2 | 1 | Jane
3 | 4 | David
4 | 2 | Emily
Now when I select that list I sort it via the position field.
What I want to do is manage this order via a backend and whilst I have the main principle down, one thing that I am struggling with is the situation where a someone updates say Emily to 3 without changing the others in that ordered list.
So the page that updates the order just has the persons name and a text box with the current order in it.
I want to try to work out a way to handle this but can't seem to grasp any possible way to do this as all will be saved at once so there is no way to determine which item has changed, and therefore should be the correct one in case of duplicate.
Any ideas?
I'd just sort like this:
...order by position, person
That way, people with the same 'position' will still be ordered reliably (by name). Leave the "fixing" up to the user.
Ofcourse, the best way to handle this would be to not bother the user at all with a 'position' field but use a draggable sortable list of some kind.
If you want to move Emily DOWN the list her position 2 become 3.
So you need to move 3 back up to 2 (which was Emilys position)
The same goes for moving UP the list. You are basically swapping positions of the next/previous record. BUT you need to check that there is a record to swap with.
PSEUDO CODE MOVE DOWN:
get Emily
update record below Emily (Emily's position+1)
IF updated okay - update Emily position
One logic behind reordering a list manually would be to reorder the entire relevant list items whenever one list position is changed. Changing 10 to 2 would require everything from 2 to 9 to be pushed +1 position forward, so the logic would be
for i in new pos+1..old pos
pos[i]++
here is an exemple that i use
first i change the position of the row, lets use calendar_event_id = 7 as exemple , and then i call reposition, that runs:
SET #position = 0;
UPDATE calendar_events SET position = #position := #position + 1
WHERE position >= 0
ORDER BY position, IF(calendar_event_id = 7, 0, 1), name
and if you deleted a row, just skip the IF(calendar_event_id = 7, 0, 1), part

Tracking a conversation in PHP MYSQL

Background: I have been working with twitter API. Have it setup so that when someone mentions/messages me, it gets sent to a chatbot. Bot make reply, I tweet it out using API.
Each tweet has a unique status_id in addition to a field called rep_to_stat_id so a conversation looks like this:
person 'hi how are you?' stat_id = 1 rep_to_stat_id = blank
me 'ok, and you?' stat_id = 2 rep_to_stat_id = 1
person 'are you stalking me' stat_id = 3 rep_to_stat_id = 2
me 'no you are stalking me' stat_id = 4 rep_to_stat_id = 3
etc.
When I send to bot first time, make a random converstation ID (conv_id) so the bot can track the conversation.
Problem is tracking this, it's like a ladder, leading up to the original stat_id with no rep_to_stat_id, and has to include the common conv_id.
Up until now I have always had tables with a one to many type setup, I cannot get my head around what type of structure this is.
Is there an option in mysql to add to query to follow a ladder of each conversation to its first/last point?
There are many ways to store hierarchical data in relational databases.
One of the most common ways is to simply have a table with all the columns you mentioned (stat_id, rep_to_stat_id [nullable], and conv_id). The problem is, to retrieve the full tree up to the root node, you'd need a recursive function (in MySQL or your scripting language of choice), making several queries.
This Stack Overflow question should give you a nice overview of all the available options for modelling your tree structure.
Have one column tag the conversation_id, and another that tracks the iteration within that conversation.
person text conversation_id reply_num
------------------------------------------------------------------
0 "Hi" 0 0
1 "Hello, who are you" 0 1
0 "I am a bot" 0 2
1 "Goodbye" 0 3
0 "Hi" 1 0 //new conversation thread
1 "who is this?" 1 1
0 "This is a bot" 1 2
1 "leave me alone" 1 3

How to Store Multiple Options selected by User in a Table

So I want my users to be able to restrict who may contact them.
There are several factors they should be able to filter, including Age (e.g. Must be between 18 - 29), income (must earn between $25,000 - $60,000), what they're looking for (e.g. Friendship, Hang out, etc.), what drugs they do (Marijuana, Meth, Cocaine, etc), etc.
The problem is, I want them to be able to select and store multiple choices for some of the criteria (e.g. drugs), but I do not know how I should store that in the DB or how I should structure the table to best accomplish that.
For example, how would I store a user's row that for "drugs" chose "Marijuana", "Cocaine", and "Heroin" within this context? Would I simply store those as comma-separated values in the "Drugs" column? Or should I do it in a completely different way?
What would be the best way to do this (considering I will obviously have to retrieve and check this information every time a user wants to contact another user) and why?
No, don't store the values in CSV format in the database. Instead create a join table called user_drug and store one row for each user/drug combination:
user
id name income
1 Foo 10000
2 Bar 20000
3 Baz 30000
drug
id name
1 Marijuana
2 Cocaine
3 Heroin
user_drug
user_id drug_id
1 1
1 2
2 1
2 3
3 3
A DB column (at least theorethically) should NOT hold multiple values. Unfortunately, there are some programmers that store multiple values in a single column (values separated by comma for examples) - those programmers (in most cases) destroy the concept of DB and SQL.
I suggest you to read about Database Normalization to get a start in organizing your tables. And, do your best to achieve the Codd's Third Normal Form
You can try with this:
criterium
------------
user_id type value
1 AGE_MIN 18
1 AGE_MAX 29
1 INCOME_MIN 25000
1 INCOME_MAX 60000
1 DRUGS Marijuana
1 DRUGS Meth

Select records with values up to and over (but only one over) another value?

I have data such as...
ID | Amount
-----------------
1 | 50.00
2 | 40.00
3 | 15.35
4 | 70.50
etc. And I have a value I'm working up to, in this case let's say 100.00. I want to get all records up to 100.00 in order of the ID. And I want to grab one more than that, because I want to fill it up all the way to the value I'm aiming for.
That is to say, I want to get, in this example, records 1, 2, and 3. The first two total up to 90.00, and 3 pushes the total over 100.00. So I want a query to do that for me. Does such a thing exist in MySQL, or am I going to have to resort to PHP array looping?
Edit:
To put it in English terms: Let's say they have $100 in their account. I want to know which of their requests can be paid, either in toto or partially. So I can pay off the $50 and the $40, and part of the $15.35. I don't care, at this point in the program, about the partialness; I only want to find out which quality in any way.
Yes, is possible
set #total:=0;
select * from
(
select *, if(#total>100, 0, 1) as included, #total:=#total+Amount
from your_table
order by id
) as alls
where included=1
order by id;
Refering to the last sentence: doesn't mysql sum cut it?

Categories