iT邦幫忙

0

資料想要讓使用者自訂項目順序排列要如何實作比較簡單?

cojad 2013-06-04 15:52:0012609 瀏覽

開發環境: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命令, 請問各位先進有沒有更好的解法?疑惑
我覺得這樣實在太沒有效率了毆飛

看更多先前的討論...收起先前的討論...
外獅佬 iT邦大師 1 級 ‧ 2013-06-04 23:59:32 檢舉
這個資料量...執行幾次SQL...user的感覺並不會很明顯...落寞
wiseguy iT邦超人 1 級 ‧ 2013-06-05 00:23:53 檢舉
設計 Web AP 不能醬思考。因為 Web AP 是給若干數量的 user 同時使用的。所以即使一個user 的使用量很微不足道,但人數一多就會是問題了。
我上司老是扯《要有 handle 一百萬 concurrent online 的能力》。雖然是扯了點 (咱們的軟體可以有一百萬 user 就削爆了),聽聽就好,不過倒是 Web AP 的設計理念沒錯。
外獅佬 iT邦大師 1 級 ‧ 2013-06-05 00:52:24 檢舉
所以,要妥善借用SP...開心
還是把Table跟測試資料列一下,還有邏輯性說一下.
所謂自訂排序順序是每個使用者有其優先的欄位排序?
抑或是沒有順序,就是每個人自己再去挪動?
到底是排序,還是每個人玩乾坤大挪移?
先釐清問題會比較好.
若是沒有Table,光是用講的,就容易失焦了.
wiseguy iT邦超人 1 級 ‧ 2013-06-05 09:11:03 檢舉
比如網路商店系統,它的結構是
1. 可以給多人開店,每個人有 user_id。
2. 每個店長可以新增多個商品,每個商品有自動產生的序號 data_no,當然還有其它細項屬性。
3. 每個店長可以對自己若干商品做排序,比如讓比較熱門的排在列表上面。當然,假如使用者沒有排序,那麼商品列表也許是依新增的先後順序排,或者完全 depend on 資料庫的行為。

所以這個排序是店長新增商品之後,可以再對其列表進行排列。每個店長排自己的,與他人無關。
14
wiseguy
iT邦超人 1 級 ‧ 2013-06-04 16:54:16
最佳解答

資料庫本來就不是在 handle 資料的順序用的。有序的資料只對使用的人有意義。所以做法是:

  1. 把排序資料另外開一個 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)
    );

  2. 當取出資料時,就把資料table跟排序table 做 left join,並 order by order_no,data_no。還沒排序過,就會按照 data_no 去排。

  3. 使用者在介面上調來調去,調好了之後,一次把資料 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 資料的順序用的。

這句話可能有點誤會了
忙

wiseguy iT邦超人 1 級 ‧ 2013-06-04 23:42:12 檢舉

也許我講的不清楚。
應該說,順序對資料庫沒有意義,只對使用資料的人有意義。而索引的目的是為了能更快速地定位到該筆資料,也不是為了排序。
所以資料存進資料庫時,它不會去刻意照什麼順序排。只有在 select 出來時,才會依照使用者的需求,按 order 去排序。假如沒 order,那麼 select 出來的資料不見得是排序的。

外獅佬 iT邦大師 1 級 ‧ 2013-06-05 00:11:26 檢舉

超人說的極是...排序對資料庫的儲存是沒有意義的...對使用資料的人才有意義。

我明白你的意思
只是我誤會了
下雨

iT邦幫忙MVPwiseguy提到:
用擴充式 insert 一次插入所有排序資料

另外請教一下
1.擴充式 insert 是通用語法還是只有特定資料庫才支援?
2.有擴充式 insert,有沒有擴充式 update?
謝謝

外獅佬 iT邦大師 1 級 ‧ 2013-06-05 08:41:24 檢舉

海綿真是好學的生物啊....讚

wiseguy iT邦超人 1 級 ‧ 2013-06-05 09:26:39 檢舉

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 起來不就好了嗎?

ted99tw iT邦高手 1 級 ‧ 2013-06-05 09:34:02 檢舉

wiselou提到:
好學的生物

我高一就死在生物,一大堆嘌呤嘧啶什麼的...暈

了解,今天又多學了一點,賺到了
謝謝

wiseguy出處提到:
如果要把多個 update 合成一個,就把 where 條件 or 起來不就好了嗎?

我這問題是替發問人問的
看看可不可以用一個擴充式Update取化9個Update指令
下雨

cojad iT邦新手 3 級 ‧ 2013-06-05 11:22:19 檢舉

經過一晚的整理, 感謝超人給的邏輯,我有信心完全解決我手上的問題了!!放馬過來
太感謝大家熱情的討論與指導了,更謝謝超人把整個table結構都給了很清楚的示範
已另外一個小table來儲存user的自訂順序,還能利用join直接order出使用者的順序
不但效能損失小, 程式做起來也很輕鬆。筆記
真是太感謝了!!灑花

6
Albert
iT邦高手 1 級 ‧ 2013-06-04 20:57:41

不同 [角色] + [使用者]

可以設定不同 ORDER BY 欄位

Customization Window OrderBy Column 可依據 Role / User 設定

請參考 iDempiere/ADempiere/Openbravo 設計

技術轉移顧問
Skype: Adempiere/Compiere
Albert

看更多先前的回應...收起先前的回應...
cojad iT邦新手 3 級 ‧ 2013-06-04 21:00:07 檢舉

albertachen提到:
ADempiere

就說了環境是PHP+MySQL
您來亂的嗎?!冷

Albert iT邦高手 1 級 ‧ 2013-06-04 23:06:08 檢舉

ADempiere 能夠

你也能夠

cojad iT邦新手 3 級 ‧ 2013-06-04 23:54:55 檢舉

等我把ADempiere的相關程式碼找到並且看懂,才能寫出來的話,我大概也可以走路了。翻桌
可以參考的open source那麼多,我還寧願去參考PTT BBS站的使用者自訂排序我的最愛看板排序的程式碼...落寞
就是希望能盡快解決問題,也避免走入誤區,才來IT幫求救的,你推廣Adempiere也好歹把那段相關程式碼給弄出來,你這種作法簡直就像是把一本沒有索引的字典扔給我,對我說裡面一定有相關的例句一樣不負責任。落寞

外獅佬 iT邦大師 1 級 ‧ 2013-06-04 23:55:55 檢舉

cojad提到:
Adempiere也好歹把那段相關程式碼給弄出來

哇靠...整套ERP的source...你打算看多久?

Albert iT邦高手 1 級 ‧ 2013-06-05 11:11:39 檢舉

cojad 說:
等我把ADempiere的相關程式碼找到並且看懂,才能寫出來的話,我大概也可以走路了。
可以參考的open source那麼多,我還寧願去參考PTT BBS站的使用者自訂排序我的最愛看板排序的程式碼...
就是希望能盡快解決問題,也避免走入誤區,才來IT幫求救的...(恕刪)

不跟公司爭取 60歐元一小時的技術顧問費
也不自己好好讀 30小時
當然很無奈

10
海綿寶寶
iT邦超人 1 級 ‧ 2013-06-04 21:17:43

提供另一種做法供參考:
問題1的答案請用 wiseguy 大大的做法
問題2的答案是「加大數字間距,以減少全部重排的頻率」

如上圖
只要改一筆(第10筆)索引值即可

看更多先前的回應...收起先前的回應...
cojad iT邦新手 3 級 ‧ 2013-06-04 23:48:48 檢舉

我有想過這種方法, 這樣就是要求出要插入的順序的前一項與後一項的中間數,更改進去就可以了,對吧?
在項目數少的狀態下,把間距塞滿的情況應該不容易發生
如果項目數多的話,數字的間距夠不夠大就成問題了,要另外寫判斷是否還有間距可以塞,如果沒間距可以塞,就要更改前一項或後一項的數字。

感覺上wiseguy的做法我的腦細胞可以死比較少點 汗

外獅佬 iT邦大師 1 級 ‧ 2013-06-04 23:55:10 檢舉

cojad提到:
腦細胞可以死比較少點

放心...每天自然死的數量,比你想像的多非常多

cojad iT邦新手 3 級 ‧ 2013-06-05 00:04:58 檢舉

放心...每天自然死的數量,比你想像的多非常多

您知道的, 我只是比喻~忙

外獅佬 iT邦大師 1 級 ‧ 2013-06-05 00:08:16 檢舉

其實...我不知道的...我沒聽過動腦想...會導致腦細胞死亡...謝謝

cojad iT邦新手 3 級 ‧ 2013-06-05 00:15:51 檢舉

理論上動腦越多, 腦神經繫結強度越緊密, 對腦袋是好事。
我真的只是比喻而已啊....抗議

外獅佬 iT邦大師 1 級 ‧ 2013-06-05 00:17:50 檢舉

不好意思...沒惡意,喇賽而已汗

cojad iT邦新手 3 級 ‧ 2013-06-05 00:20:13 檢舉

我也只是怕場子冷掉,一直跟您牽拖啦!~~開心

cojad提到:
在項目數少的狀態下,把間距塞滿的情況應該不容易發生

其實這跟項目數多或少無關,跟「使用者變更順序的頻率高低」有關

cojad提到:
如果項目數多的話

你題目的資料量是10到50筆,這量連「少」都稱不上

cojad提到:
感覺上wiseguy的做法我的腦細胞可以死比較少點

事情總要有人做,不是資料庫的SQL,就是你寫的程式邏輯,你高興就好

8
外獅佬
iT邦大師 1 級 ‧ 2013-06-04 23:57:47

有...不要用關聯式資料庫....
對於NoSQL來說,這只需要更新一筆資料

看更多先前的回應...收起先前的回應...
cojad iT邦新手 3 級 ‧ 2013-06-04 23:59:04 檢舉

那請教一下NoSQL的做法是?

外獅佬 iT邦大師 1 級 ‧ 2013-06-05 00:10:12 檢舉

開心...這個說來話長...你先專心搞定你的MySQL吧...
上面幾位大師提供了些不錯的作法,而且,你的資料量並不大...
9筆SQL,寫成SP也是可以...未必需要送出9次SQL command的

cojad iT邦新手 3 級 ‧ 2013-06-05 00:14:21 檢舉

wiselou提到:
SP

SP是甚麼東西的縮寫?

外獅佬 iT邦大師 1 級 ‧ 2013-06-05 00:15:45 檢舉

cojad提到:
SP是甚麼東西的縮寫?

Orz....Stored Procedure....無言

cojad iT邦新手 3 級 ‧ 2013-06-05 00:18:43 檢舉

喔...縮寫不識,講全稱我就懂了,問題是如何以Store Procedure做到你所講的事情?
而且如果還是要異動9筆record那感覺也不是真的很有效率阿疑惑

8
sam0407
iT邦高手 1 級 ‧ 2013-06-05 10:13:38

之前我有作過類似的功能需求,我的作法佷簡單,另建一個Table,就三個欄位:
1.使用者ID
2.資料Key值(實際資料Table的PK)
3.排序順序

再作一個UI,就一個ListBox,加幾個上移下移的按鈕,讓使用者可以調整資料順序,使用者按下存檔按鈕後,就把該使用者在該Table的資料刪除,再依ListBox內資料的順序Insert進該Table就完工了。

資料查詢時就Join這個Table依排序順序欄位排序即可。

我可以預料cojad大會覺得這種方式沒效率,但是說真的,使用者會一天到晚去改他資料的排序嗎?如果不會很頻繁,就將就用吧!

cojad iT邦新手 3 級 ‧ 2013-06-05 11:15:08 檢舉

wiseguy出處提到:
另建一個Table,就三個欄位:
1.使用者ID
2.資料Key值(實際資料Table的PK)
3.排序順序

這就是超人的簡易版, 超人就是比你多了擴充式insert sql,並把每一筆資料的順序用單獨一列儲存,以方便join時就能得到排序。
web ui的部分我想我大概也就是要依照你的方法做了,資料庫端應該就是參考超人的版本,反正使用者更改順序的部分動的是第只有順序對照表的table,全刪一次該使用者的排序,再用一次擴充insert一次全部插入,只要丟兩個sql query出去,這樣的效率已經相當令人滿意了。

不然我也想不到甚麼更有效率的方法XD

感謝你的意見,不管怎樣都比我原本的想法有效率多了!!讚

我要發表回答

立即登入回答