技術高超的各位 大家好
由於本人是PHP新手,專題一直無法解決有邏輯及程式上的問題
想請教各位 能幫小弟 打通腦中混亂的思緒
我們是開發PHP 一部份是連結MSSQL拉回資料庫的資料 並顯示在PHP表單上
但目前我遇到的困難是有一資料表(如下圖範例↓)
前面有幾個欄位的數值是一模一樣的但後面商品代碼與商品名稱...etc,有不一樣的資訊,
能回傳到PHP表格上能進行重複值的刪除與分類
規劃是
(如下圖網頁版表格範例↓)
(SELECT * FROM table where id = 'AA11**')
商品代碼
商品名稱
數量
(依序顯示出)
就不是很了解我該使用什麼語法能讓我去只要列出
是該使用 while($row=sqlsrv_fetch_array($result))
儲存到陣列
去echo
嗎?
或是做二維陣列?
還是 foreach
?
再去做i=0 i++
?
網路爬文找好久了...
請各位大師神救援小弟 的程式邏輯
真的很感恩
以 PHP 官網範例 來改
<?php
$serverName = "serverName\instanceName";
$connectionInfo = array( "Database"=>"dbName", "UID"=>"username", "PWD"=>"password");
$conn = sqlsrv_connect( $serverName, $connectionInfo );
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true));
}
$sql = "SELECT * FROM table where id = 'AA11**'";
$stmt = sqlsrv_query( $conn, $sql );
if( $stmt === false) {
die( print_r( sqlsrv_errors(), true) );
}
$rowcnt = 0;
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) ) {
$rowcnt = $rowcnt + 1;
if ($rowcnt==1) { //第一筆,特別處理
//1.用 $row['Id'],$row['Date'],$row['Qa1'],$row['Qa2']顯示表頭
//2.顯示表身標題列(Num, Id, Date... )
//3.用 $row['Qa3'], $row['Qa4'], $row['Qa5'] 顯示表身資料列
} else { //第二筆(含)以後
//只需用 $row['Qa3'], $row['Qa4'], $row['Qa5'] 顯示表身資料列
}
echo $row['LastName'].", ".$row['FirstName']."<br />";
}
sqlsrv_free_stmt( $stmt);
?>
歹勢,程式用抄的,忘了刪掉這列
echo $row['LastName'].", ".$row['FirstName']."<br />";
謝謝海綿寶寶您的協助,讓我在程式上有些突破
我也有研究你所po的code
但到最後 else { //第二筆(含)以後
會把其他日期的 'Qa3' 'Qa4' 'Qa5' 一起echo 出來
這樣那些資料就不是2016 10 28的了
最主要以ID與date
自動判斷會直接去區分
在else 後續部分 我需要怎麼愈切割會比較好?
謝謝您
沒注意到日期不同
修正如下
<?php
$serverName = "serverName\instanceName";
$connectionInfo = array( "Database"=>"dbName", "UID"=>"username", "PWD"=>"password");
$conn = sqlsrv_connect( $serverName, $connectionInfo );
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true));
}
$sql = "SELECT * FROM table WHERE id = 'AA11**' ORDER BY date";//要加 ORDER BY,否則就錯
$stmt = sqlsrv_query( $conn, $sql );
if( $stmt === false) {
die( print_r( sqlsrv_errors(), true) );
}
$rowcnt = 0;
$savekey = "";
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) ) {
$rowcnt = $rowcnt + 1;
if ($rowcnt==1) { //第一筆,特別處理
//1.用 $row['Id'],$row['Date'],$row['Qa1'],$row['Qa2']顯示表頭
//2.顯示表身標題列(Num, Id, Date... )
//3.用 $row['Qa3'], $row['Qa4'], $row['Qa5'] 顯示表身資料列
//4.將 Date 記錄下來
$savekey = $row['Date'];
} else { //第二筆(含)以後
//1.判斷該筆資料的 Date 是否等於 $savekey
//1.a 如果不同,表示換日期了(要顯示表頭那一堆,即上面 $rowcnt==1 的 1.2.3.)
//1.b 如果相同,只需用 $row['Qa3'], $row['Qa4'], $row['Qa5'] 顯示表身資料列
//2.將 Date 記錄下來
$savekey = $row['Date'];
}
}
sqlsrv_free_stmt( $stmt);
?>
HI 海綿寶寶 ,感謝您的幫忙
我總覺得我還是在程式上遇到問題
但為什麼最後MOS 的可樂雪碧 會只跳一個出來?
<?php
$serverName="*";
$connectionInfo=array("database"=>"*","UID"=>"*","PWD"=>"*","CharacterSet" => "UTF-8");
$conn=sqlsrv_connect($serverName,$connectionInfo);
if($conn === false ){
echo "資料庫無法連線!!!<br />";
die(print_r(sqlsrv_errors(),true));
}
$sql = "SELECT * FROM dbo.table1 WHERE id = 'AA11**' ORDER BY Date";//要加 ORDER BY,否則就錯
$stmt = sqlsrv_query( $conn, $sql );
if( $stmt === false) {
die( print_r( sqlsrv_errors(), true) );
}
$rowcnt = 0;
$savekey = "";
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) ) {
$rowcnt = $rowcnt + 1;
if ($rowcnt==1) { //第一筆,特別處理
print "======================================\n";echo "<br>";
echo "ID:";print_r($row['Id']);echo "<br>";
echo "日期:";print_r($row['Date']);echo "<br>";
echo "商店ID:";print_r($row['ShopId']);echo "<br>";
echo "商店名稱:";print_r($row['ShopName']);echo "<br>";
print "======================================\n";echo "<br>";
echo "商品ID:";print_r($row['ProdId']);echo "<br>";
echo "商品名稱:";print_r($row['ProdName']);echo "<br>";
echo "數量:";print_r($row['Qty']);echo "<br>";
print "======================================\n";echo "<br>";
//1.用 $row['Id'],$row['Date'],$row['Qa1'],$row['Qa2']顯示表頭
//2.顯示表身標題列(Num, Id, Date... )
//3.用 $row['Qa3'], $row['Qa4'], $row['Qa5'] 顯示表身資料列
//4.將 Date 記錄下來
$savekey = $row['Date'];
}
else if ($row['Date'] == $savekey) {
echo "商品ID:";print_r($row['ProdId']);echo "<br>";
echo "商品名稱:";print_r($row['ProdName']);echo "<br>";
echo "數量:";print_r($row['Qty']);echo "<br>";}
$savekey = $row['Date'];
//第二筆(含)以後
//1.判斷該筆資料的 Date 是否等於 $savekey
//1.a 如果不同,表示換日期了(要顯示表頭那一堆,即上面 $rowcnt==1 的 1.2.3.)
//1.b 如果相同,只需用 $row['Qa3'], $row['Qa4'], $row['Qa5'] 顯示表身資料列
//2.將 Date 記錄下來
// if ($row['Date'] == $savekey){
// print "======================================\n";echo "<br>";
// print_r($row['Id']);echo "<br>";
// print_r($row['Date']);echo "<br>";
// print_r($row['ShopId']);echo "<br>";
// print_r($row['ShopName']);echo "<br>";}
}
sqlsrv_free_stmt( $stmt);
?>
阿~~~~
我竟然.....
我該怎麼刪除我的留言
但為什麼最後MOS 的可樂雪碧 會只跳一個出來?
因為你只寫了 1.b 而沒完成 1.a 的部份
除了「可樂」之外
你沒發現也沒有出現 2016-10-29 那一大段「表頭」嗎?
難得看到一個比較用心的發問, 就給你詳細一點的程式
首先按照你原本的表格設計方式, 可以這樣寫(注意我把表格欄位改名了):
query.php
<?php
$pdo = require_once "sample_db.php";
$records = $pdo->query("SELECT * FROM record;");
$prevId = $prevDate = $prevShopId = null;
$rowNum = 0;
foreach($records as $data) {
if ($prevId !== $data["Id"]
|| $prevDate !== $data["Date"]
|| $prevShopId !== $data["ShopId"]
) {
$rowNum = 0;
$prevId = $data["Id"];
$prevDate = $data["Date"];
$prevShopId = $data["ShopId"];
}
if (0 === $rowNum++) {
print "======================================\n";
print "Num: {$data["Num"]}, Id: {$data["Id"]}, ";
print "Date: {$data["Date"]}, ShopId: {$data["ShopId"]}, ";
print "{$data["ShopName"]}\n";
}
print "--------------------------------------\n";
print "{$data["ProdId"]}, {$data["ProdName"]}, {$data["Qty"]}\n";
}
在終端機執行, 輸出長這樣:
======================================
Num: 1, Id: AA1100, Date: 2016-10-28, ShopId: 123123, 麥當勞
--------------------------------------
FF33A, 漢堡, 1
--------------------------------------
HB77H, 薯條, 1
--------------------------------------
RGJ32, 蕃茄醬, 2
--------------------------------------
BBDDA, 糖醋醬, 3
======================================
Num: 5, Id: AA1100, Date: 2016-10-29, ShopId: 111111, MOS
--------------------------------------
RFAXS, 可樂, 5
--------------------------------------
HJKLA, 雪碧, 4
這是 sample_db.php, 只是建樣本資料, 可略過不看
<?php
$db_filename = "db.sqlite";
$db_exists = file_exists($db_filename);
$pdo = new PDO("sqlite:$db_filename", null, null);
if (!$db_exists) {
$pdo->exec("CREATE TABLE record(Num INTEGER PRIMARY KEY, Id, Date, ShopId, ShopName, ProdId, ProdName, Qty);");
$datas = array(
array(
'Id' => "AA1100",
'Date' => "2016-10-28",
'ShopId' => "123123",
'ShopName' => "麥當勞",
'ProdId' => "FF33A",
'ProdName' => "漢堡",
'Qty' => 1
),
array(
'Id' => "AA1100",
'Date' => "2016-10-28",
'ShopId' => "123123",
'ShopName' => "麥當勞",
'ProdId' => "HB77H",
'ProdName' => "薯條",
'Qty' => 1
),
array(
'Id' => "AA1100",
'Date' => "2016-10-28",
'ShopId' => "123123",
'ShopName' => "麥當勞",
'ProdId' => "RGJ32",
'ProdName' => "蕃茄醬",
'Qty' => 2
),
array(
'Id' => "AA1100",
'Date' => "2016-10-28",
'ShopId' => "123123",
'ShopName' => "麥當勞",
'ProdId' => "BBDDA",
'ProdName' => "糖醋醬",
'Qty' => 3
),
array(
'Id' => "AA1100",
'Date' => "2016-10-29",
'ShopId' => "111111",
'ShopName' => "MOS",
'ProdId' => "RFAXS",
'ProdName' => "可樂",
'Qty' => 5
),
array(
'Id' => "AA1100",
'Date' => "2016-10-29",
'ShopId' => "111111",
'ShopName' => "MOS",
'ProdId' => "HJKLA",
'ProdName' => "雪碧",
'Qty' => 4
),
);
foreach ($datas as $data) {
$sql = <<<END_SQL
INSERT INTO record(Id, Date, ShopId, ShopName, ProdId, ProdName, Qty)
VALUES(
'{$data["Id"]}',
'{$data["Date"]}',
'{$data["ShopId"]}',
'{$data["ShopName"]}',
'{$data["ProdId"]}',
'{$data["ProdName"]}',
'{$data["Qty"]}'
);
END_SQL;
$pdo->exec($sql);
}
}
return $pdo;
但是你這資料表的設計, 如果要打分數的話, 只能給你 50 分不及格。因為你完全沒有做正規化。
這邊不跟你解釋什麼叫正規化, 網路上隨便搜尋都有資料, 自己去查。
我直接給你一個對購買清單正規化的範例, 注意這個範例沒有把正規化做完, 只做了一小步而已:
sample_db2.php
<?php
$db_filename = "db2.sqlite";
$db_exists = file_exists($db_filename);
$pdo = new PDO("sqlite:$db_filename", null, null);
if (!$db_exists) {
$pdo->exec("CREATE TABLE record(Num INTEGER PRIMARY KEY, Id, Date, ShopId, ShopName);");
$pdo->exec("CREATE TABLE items(fk_Num, ProdId, ProdName, Qty)");
$pdo->exec("INSERT INTO record(Id, Date, ShopId, ShopName) VALUES ('AA1100', '2016-10-28', '123123', '麥當勞')");
$fk_Num = $pdo->lastInsertId();
$pdo->exec("INSERT INTO items VALUES ($fk_Num, 'FF33A', '漢堡', 1)");
$pdo->exec("INSERT INTO items VALUES ($fk_Num, 'HB77H', '薯條', 1)");
$pdo->exec("INSERT INTO items VALUES ($fk_Num, 'RGJ32', '蕃茄醬', 2)");
$pdo->exec("INSERT INTO items VALUES ($fk_Num, 'BBDDA', '糖醋醬', 3)");
$pdo->exec("INSERT INTO record(Id, Date, ShopId, ShopName) VALUES ('AA1100', '2016-10-29', '111111', 'MOS')");
$fk_Num = $pdo->lastInsertId();
$pdo->exec("INSERT INTO items VALUES ($fk_Num, 'RFAXS', '可樂', 5)");
$pdo->exec("INSERT INTO items VALUES ($fk_Num, 'HJKLA', '雪碧', 4)");
}
return $pdo;
這樣子做, 你的資料庫就會有兩個表格, 一個紀錄消費的時間及店家資料, 另一個紀錄消費內容。兩個表格利用 Num 與 fk_Num 做關聯查詢, 最後出來的可以跟你原本表格的內容一模一樣。
例如利用 join 來處理, 這邊除了 sql 語法變了, 其餘程式都沒有變動:
query2.php
<?php
$pdo = require_once "sample_db2.php";
$records = $pdo->query("SELECT record.*, items.* FROM record LEFT JOIN items ON record.Num = items.fk_Num;");
$prevId = $prevDate = $prevShopId = null;
$rowNum = 0;
foreach($records as $data) {
if ($prevId !== $data["Id"]
|| $prevDate !== $data["Date"]
|| $prevShopId !== $data["ShopId"]
) {
$rowNum = 0;
$prevId = $data["Id"];
$prevDate = $data["Date"];
$prevShopId = $data["ShopId"];
}
if (0 === $rowNum++) {
print "======================================\n";
print "Num: {$data["Num"]}, Id: {$data["Id"]}, Date: {$data["Date"]}, ";
print "ShopId: {$data["ShopId"]}, {$data["ShopName"]}\n";
}
print "--------------------------------------\n";
print "{$data["ProdId"]}, {$data["ProdName"]}, {$data["Qty"]}\n";
}
最後再給你一點提示, 你的商店名稱跟商品名稱都需要正規化。而正規化請 "至少" 做到 3NF 才及格。
另外以上的程式需要在 php 5.4 以上, 且有安裝 pdo 與 sqlite 的環境才能運作。
難得看到一個比較用心的發問
+1
很感謝weiclin的協助,我也嘗試在研究各位的程式碼
我想在請問 如何嘗試不用sample_db.php 去呼叫資料
直接透過SELECT * FROM dbo.table1 WHERE id = 'AA11**'
去抓所有的資料
並將資料做成陣列
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) ) {
程式怎麼改會比較好
sample_db.php 那個只是我用來建立樣本資料用的而已, 實際上你只要看 query.php 裡面的邏輯即可。因為我用的是 sqlite 資料庫當範例, 所以你會覺得看起來怎麼不一樣, 但用的都是 sql。雖然語法可能有點差異, 但只用到很基本的功能所以查一下應該都能作到。
幫你劃重點, 我的這兩行:
$records = $pdo->query("SELECT * FROM record;");
foreach($records as $data) {
跟你的這兩行對應, 一行是在查詢, 另一行是對查詢結果做處理。:
$stmt = sqlsrv_query( $conn, $sql );
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) ) {
另外 $data 跟 $row 變數名稱雖然不一樣, 但其實是一樣的東西。$rowNum 跟 $rowcnt 也是差不多用意, 但我的寫法 $rowNum 在第一筆會是 0。重點是其中的邏輯, 那就是你要的東西。
感謝 weiclin,
我現階段的已經問題解決了
真的很感謝
解決就好, 加油吧