開發環境:PHP + MySQL
我有數個資料數量都是大約10~50筆的資料表。
因為每個user常用的資料是不同筆,所以希望能讓user能夠自己選擇他看到的資料是自己喜歡的先後順序。
問題:
1.我應該要如何儲存使用者的自己定義的順序?
2.當使用者調整第10項變成第3項時,我要如何對資料異動最少的狀況讓原本的第3~9項馬上變成4~10項?
我目前只有想到最土法煉鋼的方法是重編一次索引號碼
10->-1
9->10
8->9
7->8
6->7
5->6
4->5
3->4
-1->3
可是這樣我就要送出高達9次的update sql命令, 請問各位先進有沒有更好的解法?
我覺得這樣實在太沒有效率了
資料庫本來就不是在 handle 資料的順序用的。有序的資料只對使用的人有意義。所以做法是:
把排序資料另外開一個 table 來存,這樣就可以避免調整順序時,去異動原本的資料 (指標概念)。table 可能長得像醬:
<pre class="c" name="code">create table DATA_SEQUENCE (
user_id int unsigned not null, /* 使用者序號 /
data_no int unsigned not null, / 資料序號 /
order_no int unsigned not null, / 排序序號 */
primary key (user_id, data_no)
);
當取出資料時,就把資料table跟排序table 做 left join,並 order by order_no,data_no。還沒排序過,就會按照 data_no 去排。
使用者在介面上調來調去,調好了之後,一次把資料 post 到 php 時,只要兩個SQL
a. 刪掉此 user 的所有排序資料:delete from DATA_SEQUENCE where user_id=1;
b. 用擴充式 insert 一次插入所有排序資料:insert into DATA_SEQUENCE (user_id,data_no,order_no) values (1,10,1),(1,9,2),(1,8,3),...
程式就醬。剩下的就是你的 web 介面怎麼做得比較容易操作排序的問題了。
iT邦幫忙MVPwiseguy提到:
資料庫本來就不是在 handle 資料的順序用的。
這句話可能有點誤會了
也許我講的不清楚。
應該說,順序對資料庫沒有意義,只對使用資料的人有意義。而索引的目的是為了能更快速地定位到該筆資料,也不是為了排序。
所以資料存進資料庫時,它不會去刻意照什麼順序排。只有在 select 出來時,才會依照使用者的需求,按 order 去排序。假如沒 order,那麼 select 出來的資料不見得是排序的。
超人說的極是...排序對資料庫的儲存是沒有意義的...對使用資料的人才有意義。
我明白你的意思
只是我誤會了
iT邦幫忙MVPwiseguy提到:
用擴充式 insert 一次插入所有排序資料
另外請教一下
1.擴充式 insert 是通用語法還是只有特定資料庫才支援?
2.有擴充式 insert,有沒有擴充式 update?
海綿真是好學的生物啊....
1.擴充式 insert 是通用語法還是只有特定資料庫才支援?
這是 SQL92 所制定的語法。目前 DB2, SQL Server (since version 10.0 - i.e. 2008), PostgreSQL (since version 8.2), MySQL, sqlite (since version 3.7.11) 和 H2 都支援。出處。
2.有擴充式 insert,有沒有擴充式 update?
沒有。如果要把多個 update 合成一個,就把 where 條件 or 起來不就好了嗎?
wiselou提到:
好學的生物
我高一就死在生物,一大堆嘌呤嘧啶什麼的...
了解,今天又多學了一點,賺到了
wiseguy出處提到:
如果要把多個 update 合成一個,就把 where 條件 or 起來不就好了嗎?
我這問題是替發問人問的
看看可不可以用一個擴充式Update取化9個Update指令
經過一晚的整理, 感謝超人給的邏輯,我有信心完全解決我手上的問題了!!
太感謝大家熱情的討論與指導了,更謝謝超人把整個table結構都給了很清楚的示範
已另外一個小table來儲存user的自訂順序,還能利用join直接order出使用者的順序
不但效能損失小, 程式做起來也很輕鬆。
真是太感謝了!!
不同 [角色] + [使用者]
可以設定不同 ORDER BY 欄位
Customization Window OrderBy Column 可依據 Role / User 設定
請參考 iDempiere/ADempiere/Openbravo 設計
技術轉移顧問
Skype: Adempiere/Compiere
Albert
等我把ADempiere的相關程式碼找到並且看懂,才能寫出來的話,我大概也可以走路了。
可以參考的open source那麼多,我還寧願去參考PTT BBS站的使用者自訂排序我的最愛看板排序的程式碼...
就是希望能盡快解決問題,也避免走入誤區,才來IT幫求救的,你推廣Adempiere也好歹把那段相關程式碼給弄出來,你這種作法簡直就像是把一本沒有索引的字典扔給我,對我說裡面一定有相關的例句一樣不負責任。
cojad提到:
Adempiere也好歹把那段相關程式碼給弄出來
哇靠...整套ERP的source...你打算看多久?
cojad 說:
等我把ADempiere的相關程式碼找到並且看懂,才能寫出來的話,我大概也可以走路了。
可以參考的open source那麼多,我還寧願去參考PTT BBS站的使用者自訂排序我的最愛看板排序的程式碼...
就是希望能盡快解決問題,也避免走入誤區,才來IT幫求救的...(恕刪)
不跟公司爭取 60歐元一小時的技術顧問費
也不自己好好讀 30小時
當然很無奈
提供另一種做法供參考:
問題1的答案請用 wiseguy 大大的做法
問題2的答案是「加大數字間距,以減少全部重排的頻率」
如上圖
只要改一筆(第10筆)索引值即可
我有想過這種方法, 這樣就是要求出要插入的順序的前一項與後一項的中間數,更改進去就可以了,對吧?
在項目數少的狀態下,把間距塞滿的情況應該不容易發生
如果項目數多的話,數字的間距夠不夠大就成問題了,要另外寫判斷是否還有間距可以塞,如果沒間距可以塞,就要更改前一項或後一項的數字。
感覺上wiseguy的做法我的腦細胞可以死比較少點
cojad提到:
腦細胞可以死比較少點
放心...每天自然死的數量,比你想像的多非常多
放心...每天自然死的數量,比你想像的多非常多
您知道的, 我只是比喻~
其實...我不知道的...我沒聽過動腦想...會導致腦細胞死亡...
理論上動腦越多, 腦神經繫結強度越緊密, 對腦袋是好事。
我真的只是比喻而已啊....
有...不要用關聯式資料庫....
對於NoSQL來說,這只需要更新一筆資料
之前我有作過類似的功能需求,我的作法佷簡單,另建一個Table,就三個欄位:
1.使用者ID
2.資料Key值(實際資料Table的PK)
3.排序順序
再作一個UI,就一個ListBox,加幾個上移下移的按鈕,讓使用者可以調整資料順序,使用者按下存檔按鈕後,就把該使用者在該Table的資料刪除,再依ListBox內資料的順序Insert進該Table就完工了。
資料查詢時就Join這個Table依排序順序欄位排序即可。
我可以預料cojad大會覺得這種方式沒效率,但是說真的,使用者會一天到晚去改他資料的排序嗎?如果不會很頻繁,就將就用吧!
wiseguy出處提到:
另建一個Table,就三個欄位:
1.使用者ID
2.資料Key值(實際資料Table的PK)
3.排序順序
這就是超人的簡易版, 超人就是比你多了擴充式insert sql,並把每一筆資料的順序用單獨一列儲存,以方便join時就能得到排序。
web ui的部分我想我大概也就是要依照你的方法做了,資料庫端應該就是參考超人的版本,反正使用者更改順序的部分動的是第只有順序對照表的table,全刪一次該使用者的排序,再用一次擴充insert一次全部插入,只要丟兩個sql query出去,這樣的效率已經相當令人滿意了。
不然我也想不到甚麼更有效率的方法XD
感謝你的意見,不管怎樣都比我原本的想法有效率多了!!