SQL - Get data from 2 tables - php

I've read other threads about getting queries from 2 tables, but I still don't now how to implement my issue.
There is a Feed page where user gets queries from Table A sorted by date. And there is another Table B that contains some queries. I need to get queries from both tables, mix them, and sort by date.
Table A
----id---- ----date---- ----post----
1 20170514 post 1
2 20170512 post 3
3 20170510 post 5
Table B
----id---- ----date---- ----post---- ----thread----
1 20170513 post 2 1
2 20170511 post 4 2
SELECT * FROM tableA WHERE post!="" AND date!="" and SELECT * FROM tableB WHERE post!="" AND date!=""
Output (in plaint text to screen) should be:
table: Table A, post: post 1, date: 20170514
table: Table B, post: post 2, date: 20170513
table: Table A, post: post 3, date: 20170512
table: Table B, post: post 4, date: 20170511
table: Table A, post: post 5, date: 20170510

You can use UNION like this
SELECT id, date, post FROM TABLEA
WHERE date IS NOT NULL AND
post IS NOT NULL
UNION
SELECT id, date, post FROM TABLEB
WHERE date IS NOT NULL AND
post IS NOT NULL
you may need to use alias for the tables.

If you'd like to see a result-set containing both tables' rows, you should use JOIN but in this case, you should be able to connect those two tables. For example if you have a product table, and a product_details, then you should have a field on the second table like product_id which is pointing to an existing product's id. you can find out more here:
https://www.w3schools.com/sql/sql_join.asp
Otherwise you could try UNION which is used to combine two ore more result-ser of multiple SELECT statements:
https://www.w3schools.com/sql/sql_union.asp

Related

PHP combine two tables and list all from first table

I want to combine two tables.
table A: has multiple posts with unique URL and table B has votes for specific posts from table A.
Now I want to list all rows from table A and if a post has a vote in table B to attach that to one row.
I've tried this, but it excludes the posts who matches the table A with table B. It returns only without any votes.
SELECT a.id,a.url,a.content,a.sourcetype,a.width,a.height,a.totalvotes,a.score, b.postid,b.userid,b.votetype
FROM create_general a
LEFT JOIN votes b ON a.url=b.postid
WHERE a.status='1' and a.score > 0 order by a.url desc
LIMIT 24
Perhaps it would be nice to know more about the table structure, but you definitely do something wired in your on clause:
ON a.url=b.postid
This says, that the "url" in "table a" has to be the same than the "postid" in "table b".
Usually a url would look like this: "https://google.de" and a postid is just a number, perhaps "7", so they cannot be the same.

Retrieving data from multiple tables and listing them in a list

I'm having some problems retrieving data from two tables and then listing them. I'd like to list the user's feed posts and their likes activity all in one.
Feeds - Table for users posts
Likes - Table for users likes (So when a use likes a post, a record is added to likes (Table likes contains data which contains the feeds ID of the post liked)
What I'm attempting to make: List BOTH feeds and user's Like activity in an ACTIVITY WALL.
So it should output like (ordered by timestamp desc):
"THIS IS A POST by user A"
Shows that user C liked user B's post
"THIS IS A POST by user B"
"THIS IS A POST by user L"
Shows that user A liked user F's post
"THIS IS A POST by user F"
-and it goes on-
My current SQL:
SELECT * FROM feeds,likes WHERE feeds.deleted!=0 or likes.deleted!=0 ORDER BY feeds.timestamp, likes.timestamp
However, my problem is I have no idea how to link both tables, since the IDs in my 'feeds' differ from those in 'likes'
To combine the two sets, you can use a UNION ALL set operator.
Something like this:
SELECT f.timestamp AS `timestamp`
, 'feed' AS `src`
, f.feed_id AS `id`
, f.feed_content AS `content`
FROM feeds f
WHERE f.deleted!=0
UNION ALL
SELECT l.timestamp AS `timestamp`
, 'like' AS `src`
, l.like_id AS `id`
, l.note AS `content`
FROM likes l
WHERE l.deleted!=0
ORDER BY 1 DESC
Note the the queries (on either side of the UNION ALL operator) need to match, in terms of the number of columns returned, and the datatype of each column.
To accommodate differences, such as extra columns returned from one table, but not from the other, you can add literal expressions in place of the "missing" columns.
The return of the extra src column is one way we can use to distinguish which query a row was returned by. It's not mandatory to return such a column, but it's something I often find useful. (The src column could be removed from each query, if it's not useful for your use case.)
Note that it's also possible to combine the results from more than two queries in this way, we'd just add another UNION ALL and another query.
The column names in the combined resultset are determined from the first query. The column names and aliases in the second query are ignored.
The ORDER BY applies to the entire set, and follows the last select.
Query should be linked via postID
F=feeds table, L=likes table, U1=usertable linked to owned feeds, U2=usertable linked to likes table
SELECT F.postTitle+' posted by '+ U1.username,'liked by'+U2.username
FROM likes L
LEFT JOIN feeds F on (F.postID=L.postID)
LEFT JOIN users U1 on (U1.userID=F.userID)
LEFT JOIN users U2 on (U2.userID=L.userID)
ORDER BY L.date,L.postID DESC
When you write SELECT * FROM feeds,likes... you are implicitly CROSS JOINing both tables. The engine will combine every record in each table with every record in the other. That is far from what you want.
I don't think you should be "linking" both tables, either. What you need, roughly speaking, is to get every post and every like, and then order that big set according to timestamps.
It sounds more like a UNION between two queries, and an ORDER BY applied to the whole UNION. UNIONs are never easy on the eye, by the way...
The thing with UNIONs is that both sub-queries need to return the same amount of columns. Not knowing exactly which columns you have, I'll show you one possible solution:
SELECT activity, timestamp FROM (
( SELECT CONCAT(u.name,' posted ',f.content) as activity, timestamp
FROM user u
JOIN feed f on (f.user_id=u.id)
WHERE f.deleted!=0
) UNION
( SELECT CONCAT(u.name, ' liked a post by ',u2.name) as activity, timestamp
FROM user u
JOIN likes l on (l.user_id=u.id)
JOIN feed f on (l.feed_id=f.id)
JOIN user u2 on (f.user_id=u2.id)
WHERE l.deleted!=0
)
) as whole_result
ORDER by timestamp desc
You should, of course, modify this to match your structure.
Hope this helps!
I think, it's better to use 3rd table, say, "actions", and insert to it real actions. Then just select rows from this table, joined to "posts" & "users" table.
When user posts articles, o likes an article, insert corresponding row to "actions" table.
actions table:
|id|action_name|user_id|post_id| date |
1 posted 3 3 5/7/2014
2 liked 5 3 5/7/2014
3 liked 4 3 6/7/2014
4 posted 5 6 7/7/2014
5 liked 3 6 7/7/2014
SELECT user_name a, post_title b, action_name c FROM actions c LEFT JOIN users a ON a.id=c.user_id LEFT JOIN posts b ON b.id = c.post_id ORDER BY c.date DESC LIMIT 10
Then, in loop, choose how to display this data, according to "action_name".
In such way you can expand your wall for other activities, +use indexes for better database performance.

MySQL Inner Join Returning Multiples of the Same Row

I have two MySql Tables as follows:
resource
-----------------------------------------------
id name group owner_id
-----------------------------------------------
1 MyResource1 hs 11
2 MyResource2 ms 24
3 MyResource3 ps 11
...
resource_access
-----------------------------------------------
id resource_id user_id
-----------------------------------------------
1 1 12
2 2 24
3 2 11
4 3 15
...
Now, the first table is a list of resources, of course, and their respective owners in the owner_id column. The second table is the result of "sharing" this resource with another user. The table resource_access may contain records with a user_id that is equivalent to the owner_id in a row of the resource_access as a result of messy cleanup from an owner exchange.
I simply want to get the id, name, and group of any resource that a user has access to, whether they are the owner or it has been shared with them. Here is my MySQL query for an example user (24):
SELECT resource.id, resource.name, resource.group
FROM `resource`
INNER JOIN resource_access ON (
resource.owner_id='24'
OR (
resource_access.user_id='24' AND
resource_access.resource_id=resource.id
)
)
Right now, it returns the id, name, and group for resource number 2 multiple times (like twelve). Is there a possible cause for this? I have tried LEFT and RIGHT joins and am getting the same result. There are many records in the resource table, but none with the id of 2. There are no duplicate rows in resource_access sharing the resource with the same user twice.
Thanks in advance.
Use:
SELECT DISTINCT resource.id, resource.name, resource.group
to remove duplicates.
The way an inner join conceptually works is that it produces a full cross-product between the two tables. This cross-product contains a row for each pair of rows in the input tables. Then it keeps the rows that match all the ON and WHERE conditions, and returns this as the result set. If there are multiple matching rows between the two tables, you'll get multiple rows in the result set.
If you were selecting columns from both tables, you would see that they're not actually the same row. They just have the same data from the resource table, but different data from the resource_access table. But you're not showing those latter columns in your result. Using DISTINCT merges all these rows in the result.
Because you are only selecting from the resource table, I would suggest putting the conditions in the where clause rather than using an explicit join:
SELECT r.id, r.name, r.group
FROM `resource` r
WHERE r.owner_id='24' or
EXISTS (select 1
from resource_access ra
where ra.resource_id = r.id and
ra.user_id = '24'
);
With this logic, the "join" cannot product duplicates.
Select the ownership of resources then union it to resources with access.
Resulting user_id column that is different from your WHERE RA.user_id value just means that resource was shared to them instead of them owning the resource. Hope this helps.
SELECT resource.name,resource.group,resource.owner_id AS user_id
FROM resource
WHERE resource.owner_id = '11'
UNION
SELECT R.name,R.group,R.owner_id AS user_id
FROM resource_access RA
LEFT JOIN resource R
ON (R.id=RA.resource_id)
WHERE RA.user_id = '11';

MYSQL count based off of two tables

Sorry for asking this, but I haven't found an answer to what I'm trying to do anywhere!
Basically, I have a database with two tables. Below or two examples I'll use:
Table 1:
Process ID Date
---------- -----------
1 2008/08/21
2 2008/08/23
3 2008/08/21
Table 2:
Process ID Qty
---------- ---
1 1
2 4
3 6
Basically, I was to do something in PHP where I will select table 1, and find all processes that occur today (in this example I'll say the 21st of August). I then want to take those process ids, and match them in Table two and give a count of their quantities.
The end result I'm trying to figure out in this example is how do I get the output to be "7" by using PHP to select the processes that happened today in one table, then add up the corresponding process quantities in another table.
SELECT sum(t2.qty)
FROM table1 t1
JOIN table2 t2 ON t1.pid = t2.pid
WHERE t1.date = '2008/08/21'

compare two table result on based of count of column of second table

I am using mysql database.
I have two table one is user_songs and second is user_like
Fields of user_song:
id(auto incement)
song_id
user_id
song_name
song_file
Fields of user_like:
id(auto incement)
song_id
uder_id
like
In user_like I am saving data where any user going like song so each row contain data like:
1 1 1 1
Please note like saves either 0 or 1.0 for dislike and 1 for like.
Now I need to find out top 20 most like songs id from user_like and get all data from user_songs from user_songs.
How to do this?
Thanks in advance to spend your valuable time to solve this query.
SELECT a.*, b.totalLike
FROM user_song a
INNER JOIN
(
SELECT song_id, COUNT(*) totalLike
FROM user_like
GROUP song_id
) b ON a.song_id = b.song_ID
ORDER BY totalLike DESC
LIMIT 20
Caution: the query above doesn't handle tie up values on totaluserLike result. It will only display 20 records on the result list.

Categories