更新为pr。 @philipxy建议在下面的评论中
(感谢输入)
我在MySQL数据库中有2个表,具有以下结构
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 |
--------------------------------------------------------------------------
(id为1的用户写了id为1的话题)
(id为5的用户使用id 2写了主题)
(id为6的用户使用id 3写了主题)
等
forumtopicview
-----------------------------
| id | userID | topicID |
-----------------------------
| 1 | 1 | 2 |
-----------------------------
| 2 | 5 | 1 |
-----------------------------
| 3 | 5 | 3 |
-----------------------------
| 4 | 6 | 1 |
-----------------------------
.
.
.
-----------------------------
| n | <userID> | <topicID> |
-----------------------------
(id为1的用户观看了上表中id为2的话题)
(id为5的用户观看了上表中id为1的话题)
(id为5的用户观看了上表中id为3的话题)
(id为6的用户观看了上表中id为1的话题)
等
我正在尝试做什么
我正在尝试获取所有未登录用户所写的主题的信息,并且已经登录的用户尚未查看
因此对于用户1:
用户1写了主题1并查看了主题2
然后,SELECT语句应显示非1和2(即3)
对于用户5:
用户5写了主题2并查看了主题1和3
然后,SELECT语句应显示非1,2和3的所有主题的信息(即无结果)
对于用户6:
用户6写了主题3并查看了主题1
然后,SELECT语句应显示非1和3(即2)
如何在单个SELECT语句中执行此操作?
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 ();
}
有效的代码,但却很麻烦:
的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'];
}
}
}
}
但这可以通过很多代码实现这个
我想做什么
的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'];
}
}
插入单个SELECT语句
而且我知道可以在一个SELECT语句中完成所有这些 - 但我已经离开'游戏'一段时间了,我似乎无法让它工作
根据建议的解决方案,应该做些什么呢?
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
它排除了用户登录的所有主题(t.userID&lt;&gt;?)
但不排除已登录用户查看的内容(t.userID = v.userID AND t.id = v.topicID)
希望有人可以提供帮助
答案 0 :(得分:2)
所有主题均未由用户撰写且未被用户查看
SELECT
t.id
, t.date
, t.dateEdit
, t.userID
, t.title
, t.summary
, t.randomString
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
注意:连接表时,在所有列引用中包含表名或表别名变得非常重要。这可以避免由常见列名引起的错误导致的歧义。
SELECT
t.id
, t.date
, t.dateEdit
, t.userID
, t.title
, t.summary
, t.randomString
FROM forumtopic t
WHERE t.userID <> ?
AND NOT EXISTS (
SELECT NULL
FROM forumtopicview v where t.id = v.topicID
AND v.userID = ?
)