[英]How to limit the number of page results based on one table in INNER JOIN SQL query or in php?
我正在嘗試每頁包含答案的問題5個(問題和答案表一對一的關系),但是,我正在獲得此聯接表每頁的記錄數,無論如何,是否有限制基於問題表的結果分頁。
<?php
$topic_id = $_GET['topic_id'];
$answers_data = [];
$questions_data = [];
if (isset($_GET["page"])) { $page = $_GET["page"]; } else { $page=1; };
$num_rec_from_page = 5;
$start_from = ($page-1) * $num_rec_per_page;
$sql = "SELECT questions.q_id,questions.question,answers.answers,answers.answer_id FROM questions INNER JOIN answers ON questions.q_id = answers.q_id WHERE topic_id='$topic_id' LIMIT $start_from, $num_rec_from_page";
$result = $connection->query($sql);
while($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
}//While loop
foreach($data as $key => $item) {
$answers_data[$item['q_id']][$item['answer_id']] = $item['answers'];
}
foreach($data as $key => $item) {
$questions_data[$item['q_id']] = $item['question'];
}
?>
我使用以下2個for-each循環獲取上述查詢數據的結果。
<?php
$question_count= 0;
foreach ($answers_data as $question_id => $answers_array) {
$question_count++;
$q_above_class = "<div class='uk-card-default uk-margin-bottom'><div class='uk-padding-small'><span class='uk-article-meta'>Question :".$question_count."</span><p>";
$q_below_class = "</p></span><div class='uk-padding-small'>";
echo $q_above_class.$questions_data[$question_id].$q_below_class;
$answer_count = 0;
foreach($answers_array as $key => $answer_options) {
$answer_count++;
$answer_options = strip_tags($answer_options, '<img>');
$ans_above_class="<a class='ansck'><p class='bdr_lite uk-padding-small'><span class='circle'>".$answer_count."</span>";
$ans_below_class = "</p></a>";
echo $ans_above_class.$answer_options.$ans_below_class;
}
echo "</div></div></div>";
}
?>
有什么想法,我如何限制基於問題表的每頁結果。
像這樣的東西
SELECT
q.q_id,
q.question,
a.answers,
a.answer_id
FROM
(
SELECT
q_id, question
FROM
questions
WHERE
topic_id=:topic_id
LIMIT
$start_from, $num_rec_from_page
) AS q
JOIN
answers AS a ON q.q_id = a.question_id
一些問題/想法/筆記。
您有question.q_id
和question.question_id
,這似乎是一個錯誤。 所以我只用了q_id
,另一個是更多的打字(我不喜歡),我有50-50的機率……
您只有topic_id
所以我不確定它來自哪個表,我假設它來自表“ question”? 差異很大,因為我們確實需要子查詢的where條件限制在哪里。
內部聯接與聯接是同一回事,所以我放聯接是因為我很懶。 我在SO上找到了上一篇有關它的文章( 請單擊此處 )
:topic_id
我參數化了您的查詢,但不進行變量串聯和SQLInjection漏洞之類的工作。 (又名,請使用准備好的語句 )命名占位符用於PDO,這就是我喜歡使用的占位符,您幾乎可以將其替換為?
對於mysqli
就像我對INNER JOIN所說的那樣,我很懶,所以我喜歡只用1個字符來別名表,這就是我所做的。 (我認為您甚至不需要AS部分,但我並不“懶”)。 有時我必須使用2,這確實讓我感到惱火,但無論如何
使用子查詢,您可以只限制該表中的行,然后像平常一樣將查詢的結果連接回主查詢。 這樣,您從問題表中拉出5
或有什么,然后僅基於對內部查詢結果的聯接而從答案中提取{n}
行。
不能真正測試它,但是從理論上講它應該可以工作。 您必須仔細檢查結果,然后按問題分組。 因為您將獲得{n}
行,其中包含相同的5
問題。 使用PDO,您可以執行PDO::FETCH_GROUP
我認為Mysqli沒有等效的方法,因此您必須手動進行操作,但這非常簡單。
這是我收集的數據庫小提琴,您可以看到它完全滿足您的需要
https://www.db-fiddle.com/f/393uFotgJVPYxVgdF2Gy2V/3
另外,我在其下放置了一個非子查詢以顯示差異。
至於小語法錯誤和表/列名之類的問題,那么我無權訪問您的數據庫,您將不得不付出一些努力以使其適應您的設置。 我僅有的信息是您在問題中輸入的內容,因此您的問題的表/列名稱錯誤。 我之前已經指出了其中一些問題。 我並不是說刻薄或屈尊,這只是一個直白的事實。
根據您的評論。 in 1st query the question is redundant
這只是數據庫的工作方式,要說明這一點非常簡單,在我的示例中,我有5個問題與8個答案相匹配。 在任何數據庫(不包括像mongoDB這樣的NoSQL)中,您都無法實際嵌套數據。 換句話說,您不能像這樣拉它。
question1
answer1
answer2
answer3
您必須將其拉平,發生的方式是這樣的
question1 answer1
question1 answer2
question1 answer3
這只是數據庫在連接數據時如何工作的自然結果。 既然這已經不可行了,我們將如何處理。 因為我們希望像第一個示例一樣嵌套數據。
偽代碼指令(我不喜歡編碼)
init data variable
query for our 5 questions
while each questions as question
- add question to data
- query for answers that belong to question
- while each answers as answer
-- add answer to nested array in data[question]
return data
偽代碼指令(用於比較)
init data variable
query for our 5 questions and their answers
while each questions&answers as row
- check if question is in data
-- if no, add question with a key we can match to it
- remove data specific to question (redundant data)
- add answers to data[question]
return data
如您所見,第二條的基本說明並不比第一條復雜(相同數量的指令)。 這只是假設每行具有相同的復雜性。 顯然,與if條件相比,SQL查詢或while循環更復雜。 您將在下面看到我如何將此偽代碼轉換為真實代碼。 實際上,我在計划項目時經常寫psudo代碼。
無論如何,這是我們需要做的。 (使用先前的SQL或小提琴中的第一個)。 這是從數據庫中提取數據的常規“標准”循環
$data = [];
while($row = mysqli_fetch_assoc($result)) {
$data[] = $row;
}//While loop
我們將對此進行一點修改(非常簡單)
//query for our 5 questions and their answers(using SQL explained above)
//init data variable
$data = [];
//while each questions&answers as row
while($row = mysqli_fetch_assoc($result)) {
// - create a key based of the question id, for convenience
$key = 'question_'.$row['q_id'];
// - check if question is in data
if(!isset( $data[$key] ) ){
//--if no, add question with a key we can match to it
$data[$key] = [
'q_id' => $row['q_id'],
'question' => $row['question'],
'children' => [] //you can call this whatever you want, i choose "children" because there is a field named "answers"
];
}
//- remove data specific to question (redundant data) [optional]
unset($data['q_id'], $data['question']);
//- add answers to data[question]
$data[$key]['answers'][] = $row;
}
//return data
所以這是什么樣子:在第一個標准時間里,我們將其稱為冗余數據。
[
["q_id" => "4", "question" => "four", "answers"=>"4", "answer_id"=>"4"],
["q_id" => "5", "question" => "five", "answers"=>"5", "answer_id"=>"5"],
["q_id" => "5", "question" => "five", "answers"=>"5", "answer_id"=>"6"],
]
對於第二個,通過更難的代碼(不是很困難),我們得到了:
[
["q_id" => "4","question" => "four","children" = ["answers"=>"4","answer_id"=>"4"]],
[
"q_id" => "5",
"question" => "five",
"children" = [
"answers"=>"5",
"answer_id"=>"5"
],[
"answers"=>"5",
"answer_id"=>"6"
]
],
]
我擴展了第二個問題,以便您可以看到嵌套。 這也是為什么它具有冗余數據以及一般情況的一個很好的例子。 如您所見,如果沒有一些冗余數據(不嵌套它們),就無法用5個共享問題來表示8行。
我最后要提到的是我選擇的$key
。 我們本可以僅使用q_id
,而無需添加question_
位。 我這樣做有兩個原因。
array_*
(和其他)函數將重置數字鍵。 因為我們在這里存儲重要數據,所以我們不想丟失這些信息。 做到這一點的方法是使用字符串。 您可以將其(int)$row['q_id']
轉換為字符串(int)$row['q_id']
,但是在某些情況下,鍵仍然可以刪除。 例如,當使用JSON編碼時,有一個標志JSON_FORCE_OBJECT
強制數字鍵成為對象{"0":"value}
但它的作用是全局的。在任何情況下,如果它們只是數字,則可能會丟失鍵,我對此不太在意,所以我給它們加了前綴以防止發生這種情況。 preg_match('/question_([0-9]+)/', $key, $match)
或$id = substr($key, 9);
這樣的事情並不難$id = substr($key, 9);
把它拉回去,我們在數組中有q_id
,檢查isset($data['question_1'])
然后再檢查isset($data['1'])
並不困難,它看起來更好。 因此,為了最小的困難,我們可以確定我們不會將ID丟失到站點上的某些代碼中(除非我們使用usort
而不是uasort
),但是我離題了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.