Updated as pr. @philipxy suggestions in comments below
(thanks for the input)
I have 2 tables in a MySQL database with the following structure
forumtopic
| id | date | dateEdit | userID | title | summary | randomString |
--------------------------------------------------------------------------
| 1 | <date> | <date> | 1 | Welcome | Welcome | jhdsa76dfasi |
| | | | | | message | |
--------------------------------------------------------------------------
| 2 | <date> | <date> | 5 | LEFT | How to | oiasud88ashk |
| | | | | JOIN | LEFT JOIN | |
--------------------------------------------------------------------------
| 3 | <date> | <date> | 6 | Not the | How to do | lkdsajlkjdf7 |
| | | | | right | it right | |
| | | | | way | | |
--------------------------------------------------------------------------
.
.
.
--------------------------------------------------------------------------
| n | <date> | <date> | <user> | title-n | summary-n | randomString-n |
--------------------------------------------------------------------------
(user with id 1 wrote topic with id 1)
(user with id 5 wrote topic with id 2)
(user with id 6 wrote topic with id 3)
etc.
forumtopicview
-----------------------------
| id | userID | topicID |
-----------------------------
| 1 | 1 | 2 |
-----------------------------
| 2 | 5 | 1 |
-----------------------------
| 3 | 5 | 3 |
-----------------------------
| 4 | 6 | 1 |
-----------------------------
.
.
.
-----------------------------
| n | <userID> | <topicID> |
-----------------------------
(user with id 1 watched topic with id 2 from the above table)
(user with id 5 watched topic with id 1 from the above table)
(user with id 5 watched topic with id 3 from the above table)
(user with id 6 watched topic with id 1 from the above table)
etc.
What I'm trying to do
I'm trying to get info on all topics that isn't written by the user logged in and haven't been viewed by the user logged in already
So for user 1:
User 1 wrote topic 1 and viewed topic 2
SELECT statement should then show info on all topics that are not 1 and 2 (ie. 3)
For user 5:
User 5 wrote topic 2 and viewed topic 1 and 3
SELECT statement should then show info on all topics that are not 1, 2, and 3 (ie. no results)
For user 6:
User 6 wrote topic 3 and viewed topic 1
SELECT statement should then show info on all topics that are not 1 and 3 (ie. 2)
How do I do that in a single SELECT statement?
connection.php
try {
$servername = "localhost";
$username = "******";
$password = "**************";
$database = "*****";
$charset = 'utf8';
$dsn = "mysql:host=$servername;dbname=$database;charset=$charset";
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO ( $dsn , $username , $password , $opt );
} catch ( PDOException $e ) {
file_put_contents ( 'PDOError.txt', $e->getMessage(), FILE_APPEND );
echo "Failed to connect to database!";
die ();
}
Code that works but is way to cumbersome:
functions.php
require ( '../scripts/connection.php' );
function getTopic ($pdo) {
// Set userID for user logged in
if ( isset ( $_SESSION['id'] ) ) {
$userID = $_SESSION['id'];
}
try {
// Find all topics not written by user logged in
$prepareTopic = $pdo->prepare( "SELECT id , date , title , summary , randomString FROM forumtopic WHERE userID != ? ORDER BY date DESC" );
$prepareTopic->execute([$userID]);
$getTopic = $prepareTopic->fetchAll();
} catch ( PDOException $e ) {
file_put_contents ( 'error.txt', $e->getMessage(), FILE_APPEND );
}
// If found topics not written by user logged in
if ( $getTopic ) {
foreach ( $getTopic as $row ) {
// Set topicID and use it to see if user logged in has already viewed it
$topicID = $row['id'];
try {
// Find if specific topic viewed by user logged in
$prepareTopicview = $pdo->prepare( "SELECT id FROM forumtopicview WHERE ( userID = ? AND topicID = ? ) LIMIT 1" );
$prepareTopicview->execute([$userID,$topicID]);
$getTopicView = $prepareTopicview->fetch();
} catch ( PDOException $e ) {
file_put_contents ( 'error.txt', $e->getMessage(), FILE_APPEND );
}
// Only if specific topic not viewed by user logged in
if ( !$getTopicView ) {
// Set needed variables
$dateTopic[] = $row['date'];
$titleTopic[] = $row['title'];
$summaryTopic[] = $row['summary'];
$randomStringTopic[] = $row['randomString'];
}
}
}
}
But this is way to much code for this
What I want to do
functions.php
if ( isset ( $_SESSION['id']; ) ) {
$userID = $_SESSION['id'];
}
try {
$prepareTopic = $pdo->( "SELECT..." );
$prepareTopic->execute([$userID]);
$getTopic = $prepareTopic->fetchAll();
} catch ( PDOException $e ) {
file_put_contents ( 'error.txt', $e->getMessage(), FILE_APPEND );
}
if ( $getTopic ) {
foreach ( $getTopic as $row ) {
$dateTopic[] = $row['date'];
$titleTopic[] = $row['title'];
$summaryTopic[] = $row['summary'];
$randomStringTopic[] = $row['randomString'];
}
}
Insert single SELECT statement
And I know it is possible to do all that in a single SELECT statement - but I've been out of the 'game' for a little while and I can't seem to get it to work
What should work is something along the lines of the suggested solution
SELECT <select_list> FROM forumtopic t LEFT JOIN forumtopicview v ON t.userID = v.userID AND t.id = v.topicID WHERE t.userID <> ? AND v.id IS NULL
And it excludes all topics written by user logged in (t.userID <> ?)
But doesn't exclude the ones viewed by user logged in already (t.userID = v.userID AND t.id = v.topicID)
Hope someone can help