Would it be possible to store a "link" to another record inside a record? For example:
table USERS
id name link
-------------------------------------------------------
1 user1 [link to record with id=4 in table info]
So, in PHP, I could do something like this:
// connect to the database etc....
$query = "select * from users where id=1";
$result = mysql_query($query);
$another_result = mysql_result($result, 0, 'link');
So that $another_result stores the result of another query, in the same raw format as if it was called using mysql_query().
Is this possible?
$query = "select info.* from info
inner join users on users.link = info.id
where users.id=1";
$result = mysql_query($query);
Using JOIN is a fundamental part of SQL, like using for loops in PHP.
Read A Visual Explanation of SQL Joins by fearless leader.
Maybe you mean a key that point to a another key in another table, so for example you can have something like this :
table USERS
id name info_id
-------------------------------------------------------
1 user1 4
table INFO
id info
--------------
4 someinfo
With a JOIN you can get for example a resultset with the "linked" fields :
SELECT u.name AS name, i.info AS info
FROM USERS u
JOIN INFO i ON u.info_id = i.id
MySql is a so called relational database and having relations (links) between tables is one of the key concepts. In your specific case the "link" you want is called a Foreign Key. You might want to have a read here (there are many more articles around if you have a look on google).
You can retrieve linked records via a JOIN operation as the other answerers have already told you.
Related
I have 2 tables, a users table and a trade table.
Which look like:
The structure of my code right now is:
<?php
$history = mysqli_query($con, "SELECT * FROM .......");
while($row = mysqli_fetch_array($history)) {
echo("The sentence");
} ?>
Problem I'm facing is that I'm trying to echo the user_name which in one case has to be the receiver and other the person giving it.
Pro tip: Never use SELECT * in software unless you know exactly why you are doing so. In your case it is harmful.
I'm assuming your query is really against the user and trade tables you mentioned in your question.
First, recast your query using 21st century SQL, as follows:
SELECT *
FROM trade AS t
JOIN user AS s ON s.user_id = t.user_id_sender
WHERE s.facebook_id = $fbid
Second, use this to retrieve your user's names and the item id traded.
SELECT s.user_name AS sender,
r.user_name AS receiver,
t.trade_id AS item_id
FROM trade AS t
JOIN user AS s ON s.user_id = t.user_id_sender
JOIN user AS r ON r.user_id = t.user_id_receiver
WHERE s.facebook_id = $fbid
See how we JOIN the user table twice, with two different aliases s (for sender) and r (for receiver)? That's the trick to fetching both names from IDs.
See how we employ the aliases sender and receiver to disambiguate the two user_name columns in the result set?
Now, when you use the php fetch_array function, you'll end up with these elements in the array.
$history['sender']
$history['receiver']
$history['item_id']
The array index strings correspond to the alias names you specified in your SELECT clause in your query.
So, one reason to avoid SELECT * is that you can get more than one column with the same name, and that means fetch_array will eliminate those duplicates and so it will lose useful information from your result set.
I have two database tables that I am using to create a Twitter-style following system.
sh_subscriptions
=> id
=> user_id
=> feed_id
sh_feeds
=> id
=> item
=> shop_name
=> feed_id
The problem with storing feed_id rather than shop_name in sh_subscriptions is that it requires a lot of table joining:
$id = $_POST['id'];
$user_id = $id['id'];
$shop_name = mysqli_escape_string($con, $_POST['shop_name']);
$query = "SELECT * FROM sh_subscriptions s INNER JOIN sh_feeds f ON s.feed_id = f.feed_id WHERE s.user_id = $user_id AND f.shop_name = '$shop_name'";
$result = mysqli_query($con, $query) or die(mysqli_error($con));
if (mysqli_num_rows($result) > 0)
{
$query2 = "DELETE FROM sh_subscriptions s INNER JOIN sh_feeds f ON s.feed_id = f.feed_id WHERE s.user_id = $user_id AND f.shop_name = '$shop_name'";
$result2 = mysqli_query($con, $query2) or die(mysqli_error($con));
}
else
{
// insert the row instead
}
(I know there's an error somewhere in the if statement, but I'll worry about that later.)
If I were to replace feed_id with shop_name, I would be able to replace line 5 with this:
$query = "SELECT * FROM sh_subscriptions WHERE user_id = $user_id AND shop_name = '$shop_name'";
My question is: is it always preferable to store MySQL values as integers where possible, or in a situation like this, would it be faster to have sh_subscriptions contain shop_name rather than feed_id?
Your sh_subscriptions table is actually a many-to-many join table that relates users to feeds. This is considered a fine way to design database schemas.
Your basic concept is this: you have a collection of users and a collection of feeds. Each user can subscribe to zero or more feeds, and each feed can have zero or more subscribers.
To enter a subscription you create a row in the sh_subscriptions table. To cancel it you delete the row.
You say there's "a lot of table joining." With respect, this is not a lot of table joining. MySQL is made for this kind of joining, and it will work well.
I have some suggestions about your sh_subscriptions table.
get rid of the id column. Instead make the user_id and feed_id columns into a composite primary key. That way you will automatically prevent duplicate subscriptions.
add an active column ... a short integer ... to the table. When it is set to a value of 1 your suscription is active. That way you can cancel a subscription by setting active to 0.
you might also add a subscribed_date column if you care about that.
create two compound non unique indexes (active,user_id,feed_id) and (active,feed_id,userId) on the table. These will greatly accelerate queries that join tables like this.
Query fragment:
FROM sh_feed f
JOIN sh_subscription s ON (f.feed_id = s.feed_id AND s.active = 1)
JOIN sh_users u ON (s.user_id = u.user_id)
WHERE f.shop_name = 'Joe the Plumber'
If you get to the point where you have hundreds of millions of users or feeds, you may need to consider denormalizing this table.. that is, for example, relocating the shop name text so it's in the sh_subscriptions table. But not now.
Edit I am proposing multiple compound covering indexes. If you're joining feeds to users, for example, MySQL starts satisfying your query by determining the row in sh_feeds that matches your selection.
It then determines the feed_id, and random-accesses your compound index on feed_id. Then, it needs to look up all the user_id values for that feed_id. It can do that by scanning the index from the point where it random-accessed it, without referring back to the table. This is very fast indeed. It's called a covering index.
The other covering index deals with queries that start with a known user and proceed to look up the feeds. The order of columns in indexes matters: random access can only start with the first (leftmost) column of the index.
The trick to understand is that these indexes are both randomly accessible and sequentially scannable.
one other note If you only have two columns in the join table, one of your covering indexes is also your primary key, and the other contains the columns in the reverse order from the primary key. You don't need any duplicate indexes.
In database in table user I have three columns:
id
name
friends
In column friends are names of people who are friends with person whose name is stored in column name. Column friends looks like this:
friendname1,friendname2,friendname3,friendname4
Each of those friends have it's own row where name is equal to their name.
I also have another table called post where I have four columns:
id
name_posted
post
visible
What I would like now, is to select all posts from table post where name_posted is equal to name of the logged in user or any of his friends which are stored in column friends in table user.
Name of the logged in user is stored in variable $user.
For selecting only posts from logged in user I can use this:
$all_posts = mysqli_query($connect_db, "SELECT * FROM post WHERE name_posted='$user' AND visible='yes'");
but I don't know how to include to select also posts from his friends. Something like Facebook have, when you log in and you see your posts plus your friends posts. I don't know how they created that. Sorry for long post, I just wanted to give you detailed description.
For selecting data based on information across multiple tables I suggest reading up on MySQL Joins.
Maybe with two querys, first select friends something like this:
SELECT * FROM user WHERE name='$user'
You then have all his friends in string like this if I understood correctly :
friend1,friend2,friend3...
Explode $row['friends'] -> explode(',',$row['friends']); to get all friends names in array and then you can do another select in foreach loop to get all posts from friends and display it the way you like or you can even better do IN in query
select * from posts where name_posted IN ($row['friends'])
this is the other way, which would be longer
foreach($friendarray as $k=>$friend){
...
mysqli_query($connect_db,
"SELECT * from post where name_posted='$friend' AND visible='yes'");
...
}
and also the query you already have to get own posts. Don't forget to escape all values and stuff...
You could also join two tables but I cant write that query from my mind , would have to sit down and try it with real data but that would be ultimate solution for you.
Don't know if I hit it right but shout if you need help
You can do it in a single query with something like:
SELECT p.*
FROM user u
join post p
on (u.name = p.name or concat(',',u.friends,',') like concat('%,',p.name,',%')
AND p.visible='yes'
WHERE u.name='$user'
- but the performance is likely to be much poorer than if you had a properly normalised design for the relationship between users and their friends.
You should probably reconsider the design of your DB. From what you've described, you should have three tables: userinfo, friendship, posts.
That way, you can then do a quick union between all three tables to get what you're looking for in one query.
Let me talk about how I will solve that case if its required from me.
I will use the following tables
users - user_id, name, email and whatever I need
relations - relation_id, user_id, fiend_id -- this table will relate one user to other
posts - post_id, user_id, content, visible
Now basically we have everything needed.
For selecting all data from the currently logged user and all of his friend I will use the following query:
SELECT * FROM posts
WHERE Visible = 1
AND (
user_id IN (SELECT friend_id FROM relations WHERE user_id = 1)
OR
user_id = 1)
What I do here, I use nested queries to accomplish that.
The interesting part here is the nested query - which basically return "array" with the ids of my friends. MySQL IN function check the user_id against that "array" After that in the main parentheses I add OR user_id = 1 which is the my user_id.
In that way I should have the content which I want to use to my feed.
However this code I away from fast and optimized but it's good example how to do that.
I am building a site and i need to retrieve some information. I have this query.
$SQL = "SELECT distretto_108, provinca_113, regioni_116, tipologia_pdv_106,
richiesta_ccnl_107, coop_va_109, nome_pdv_110,
indirizzo_pdv_111, localita_112
FROM civicrm_value_informazioni_su_tute_le_schede_p_22 ";
I need to add this other code:
WHERE civicrm_event.title_en_US='".addslashes($_GET["titles"])."'
but it's not working...
i need to compare let's say the id of another table with the id of the current table... How to do that?
Thanks in advance...
You should learn something about joining tables...
Do not know what the relation is between the two tables (simply said: what column from one table is pointing to what column at other one), but try something similar (modification needed to meet You DB structure) - now lets assume both tables have related column called event_id:
$SQL = "SELECT distretto_108, provinca_113, regioni_116, tipologia_pdv_106,
richiesta_ccnl_107, coop_va_109, nome_pdv_110,
indirizzo_pdv_111, localita_112
FROM civicrm_value_informazioni_su_tute_le_schede_p_22 cvistlsp22
LEFT JOIN civicrm_event ce ON ce.event_id = cvistlsp22.event_id
WHERE ce.title_en_US='".mysql_real_escape_string($_GET["titles"])."'";
civicrm_value_informazioni_su_tute_le_schede_p_22 table name is very long and You will not be able to create a table with such long name in other DBMS (e.g. ORACLE), so try to make it shorter while still self-describing...
If You want to join tables they have to have a relation, read more about relations and how to use them here: http://net.tutsplus.com/tutorials/databases/sql-for-beginners-part-3-database-relationships/
You are retrieving the data from table civicrm_value_informazioni_su_tute_le_schede_p_22 in your query while the where clause you are adding, refers to the table civicrm_event. You need to add this new table in the from clause and do a join among the two tables using some common key. Example below:
$SQL = "
SELECT distretto_108, provinca_113, regioni_116, tipologia_pdv_106, richiesta_ccnl_107, coop_va_109, nome_pdv_110, indirizzo_pdv_111, localita_112
FROM civicrm_value_informazioni_su_tute_le_schede_p_22
JOIN civicrm_event ON civicrm_value_informazioni_su_tute_le_schede_p_22.ID_PK = civicrm_event.ID_FK
WHERE civicrm_event.title_en_US='".addslashes($_GET["titles"])
";
You need to replace the ID_PK and ID_FK with the relevant Primary and Foreign Keys that bind the tables together.
Please note using query params like that is not recommended. Please read PHP Documentation here for more explanation.
suppose i have 1 current user id and another user id to which current user is visiting.....than i want to fetch mysql data only if both have same options.....
for example user1 has uploaded a picture and user2 has also uploaded picture.......than how can i matchd user1 to user2 and query should be like this........
select * from users where id='user1id' or id='user2id' and imguploaded='1'
is this query is correct or not but it is not working for me..........!!
i want a working query same as above not as
select * from users where imguploaded=1
try ecapsultating your where with brackets, because of the precedence...
select * from users where (id='user1id' or id='user2id') and imguploaded='1'
if you don't mysql will presume default precedence and interpret the query like this:
select * from users where id='user1id' or (id='user2id' and imguploaded='1')
which will not give the desired result.
To check if both users have actually have a picture uploaded you could make it:
select COUNT(*) as count from users where (id='user1id' or id='user2id') and imguploaded='1'
and then check if count==2
Why would you want such a thing like this?
Anyway... create some sort of actions table where you have a structure like id, action, desc Then create a user_action table like id, user_id, action_id. Then fetch your results.
This way you store data in therefore meant tables and don't mess up userdata with their action data. This way you can also easily extend actions and compare users of their made actions.
select * from users where (id='user1id' and imguploaded='1') and (id='user2id'and imguploaded='1')
How about with a join?
query = "SELECT * FROM users AS first JOIN users AS second
ON first.imguploaded = second.imguploaded
WHERE first.userid = $user1 AND second.userid = $user2"
This query would take the two users, and if they have the same attribute (imguploaded is the same for both), return both rows, you can then select what you need. You can add more attributes to the ON clause, for example:
ON first.imguploaded = second.imguploaded OR ( first.imgdloaded = second.imgdloaded AND first.somethingelseuploaded = second.somethingelseuploaded).
This way (with the ON clause of the mysql statement) you can combine all the attributes in the AND/ON but you have to place the brackets - ( and ) - in the right places. Of course, if you don't put them, the MySQL server will just read them serially.
Is that what you need?