iT邦幫忙

0

TIPTOP FOREACH

FOREACH 在tIPToP的運用方式想了解
舉例:
axmt700有所謂的銷退品項,若我現在有3項
分別為:
https://ithelp.ithome.com.tw/upload/images/20210413/20132627Rp4DbpLzvQ.jpg
https://ithelp.ithome.com.tw/upload/images/20210413/20132627SQXMX0EM3V.jpg
如果我想讓他相同品號的只列出一條,同時將後面的金額數量稅額都自動加總的話
我該怎麼用FOREACH完成

2 個回答

0
mominimaple
iT邦新手 5 級 ‧ 2021-04-13 17:28:15
最佳解答
DEFINE l_val DYNAMIC ARRAY OF RECORD
    單號     LIKE yourtable_file.單號, 
    發票號   LIKE yourtable_file.發票號,
    數量     LIKE yourtable_file.數量,
    金額     LIKE yourtable_file.金額,
    稅額     LIKE yourtable_file.稅額
END RECORD    

LET l_sql = "SELECT 單號,發票號,料號,SUM(數量),SUM(金額),SUM(稅額) FROM yourtable_file GROUP BY 料號"

PREPARE p1_prepare FROM l_sql
DECLARE p1_cur CURSOR FOR p1_prepare
LET l_ac = 1
FOREACH p1_cur INTO l_val[l_ac].*
    #想做的資料處理
    LET l_ac = l_ac + 1
END FOREACH


看更多先前的回應...收起先前的回應...
carry1246 iT邦新手 5 級 ‧ 2021-04-14 08:38:41 檢舉

可以稍微解釋一下,為什麼這麼寫
我也想學會FOREACH的用法

虎虎 iT邦新手 3 級 ‧ 2021-04-14 13:58:21 檢舉

幫忙補充~
https://ithelp.ithome.com.tw/upload/images/20210414/201036474KrA9oqh8B.png

carry1246 iT邦新手 5 級 ‧ 2021-04-14 15:53:48 檢舉

想做的資料處理指的是為何?
是像我可以下說
select 單號 INTO l_val[l_ac].單號 from ohb_file GROUP BY 單號
還是其實不用下我可以看l_val[l_ac].單號就有值可出來?

carry1246 iT邦新手 5 級 ‧ 2021-04-15 08:00:45 檢舉

而我發現我沒法用FOREACH 搞定這個...
如果我要用IF 讓他若有銅料號的SUM 出來後面的值
但當他跑的時候 第三條由於也會做判斷的話,就會造成我有兩條一模一樣的值出來,如果我要讓他只有一條出來該怎麼做呢

先感謝虎大的補充說明/images/emoticon/emoticon41.gif

在範例中l_sql的字串結果就已經是你的第二個表格的內容了,
我所指的資料處理,是指你要如何使用或是顯示這些結果,
比如說你只想要顯示銅料號,你可以在l_sql加入WHERE條件,
來過濾料號=銅料號,也可以在FOREACH中使用IF來判斷l_val[l_ac].料號=銅料號,才顯示在單身,這兩種做法都可以滿足你的需求,
我建議你可以在Debug模式中,看一下l_val這個陣列的值,你就會知道該如何運用了。

carry1246 iT邦新手 5 級 ‧ 2021-04-15 13:06:05 檢舉

新問題,我的第三條也會執行,使得我出現兩條一樣的結果出來
我該怎麼執行讓第三條在動作時,若看到相同單號、發票、料號的不再進入FOREACH回圈內

用IF判斷的話,使用 CONTINUE FOREACH 可以離開當次的結果,但是要記得順便 LET l_ac = l_ac + 1

carry1246 iT邦新手 5 級 ‧ 2021-04-15 13:21:34 檢舉

我現在有點不確定這要怎麼寫,由於我項次不一定
可能這次是1和3重覆,要將其用再一起
下一次可能是2、3重覆 要將其用再一起
我該如何寫才會符合,當我有重覆時,只有重覆項次中的第一筆會產生結果,其餘都離開

你有辦法變更FOREACH的SQL語法嗎?因為來源資料沒有一致,FOREACH就沒有規則可以判斷,太多例外情況了。

carry1246 iT邦新手 5 級 ‧ 2021-04-15 14:20:25 檢舉

我有改動
目前我的l_sql那是這麼寫的
LET l_str21="SELECT * FROM ohb_file WHERE ohb01='",g_oma.oma01,"'"
PREPARE ohb_pre FROM l_str21
DECLARE ohb_cur CURSOR FOR ohb_pre
FOREACH ohb_cur INTO l2_ohb.*

看你的SQL語法,看起來只有單純找出符合條件的資料,並沒有使用到SUM的功能,這樣會導致你要在FOREACH中處理資料總和;
建議你能把SELECT * 改成SELECT 單號,發票號,料號,SUM(數量),SUM(金額),SUM(稅額)這樣的方式,你就不用處理判斷相同料號要加總的問題。

carry1246 iT邦新手 5 級 ‧ 2021-04-15 15:00:21 檢舉

我照您建議的方式改,但我的值卻出不來...

你的SQL語法,在資料庫查詢可以正常得到值嗎?
你可以貼出語法,我幫你看看。

carry1246 iT邦新手 5 級 ‧ 2021-04-15 16:27:04 檢舉

以我在p_zta下的話
select ohb01,ohb04,ohb30,SUM(ohb912),SUM(ohb14) from ohb_file where ohb01='S602-21020017' and ohb30='KV77120490' GROUP BY ohb01,ohb04,ohb30;
這可以抓到只有兩筆,並且總和是我要的答案

那FOREACH出來的結果就會是正確的資料陣列,
另外你的l2_ohb 這個應該要宣告成DYNAMIC ARRAY OF RECORD,
你是不是只有宣告 RECORD 而已?

carry1246 iT邦新手 5 級 ‧ 2021-04-19 07:58:02 檢舉

單單宣告RECORD 和 DYNAMIC ARRAY OF RECORD,差別在哪

carry1246 iT邦新手 5 級 ‧ 2021-04-19 11:09:41 檢舉

那如果我想在現有的FOREACH中,加一個若之前已執行過此料號的資料,就不讓他再進入foreach迴圈內,可以怎麼做

單單宣告RECORD 和 DYNAMIC ARRAY OF RECORD,差別在哪
RECORD可以想像成單一個變數,比如說 a = 1
DYNAMIC ARRAY OF RECORD可以想像成陣列,比如說
a[1] = 1
a[2] = 2
a[3] = 3


那如果我想在現有的FOREACH中,加一個若之前已執行過此料號的資料,就不讓他再進入foreach迴圈內,可以怎麼做
是要在現有FOREACH中,判斷料號資料後,跳出現有FOREACH的意思嗎?
可以使用EXIT FOREACH

carry1246 iT邦新手 5 級 ‧ 2021-04-19 14:14:13 檢舉

可由於我每次重覆的項次可以說都不一樣
那我該怎麼寫這段判斷式呢

又回到原點的感覺....
最佳解還是自己重組FOREACH的SQL語法,
但你似乎有困難,我想到一個比較笨的方法...
要你自己試試看了。

FOREACH p1_cur INTO l_val[l_ac].*
    FOR l_i = 1 TO l_ac
        IF l_val[l_i].料號 = l_val[l_ac].料號 THEN
            CONTINUE FOREACH
        END IF
    END FOR
    LET l_ac = l_ac + 1
END FOREACH
carry1246 iT邦新手 5 級 ‧ 2021-04-20 15:40:43 檢舉

FOREACH 對我來說是全新的東西,讓你勞心了 T ^T

carry1246 iT邦新手 5 級 ‧ 2021-04-21 10:01:41 檢舉

這是接續著,原本回復的那段後面還是我從FOREACH那邊開始改成這樣

以下是無法控制SQL語法,需要逐筆比對FOREACH內容,把相同料號的數量、金額、稅額加總,不同料號就塞入下一個陣列

LET l_sql = "SELECT * FROM yourtable_file GROUP BY 料號"

PREPARE p1_prepare FROM l_sql
DECLARE p1_cur CURSOR FOR p1_prepare
LET l_ac = 1
FOREACH p1_cur INTO l_val[l_ac].*
    IF l_ac = 1 THEN #第一個陣列不用比對陣列
        LET l_ac = l_ac + 1 
        CONTINUE FOREACH
    END IF
    FOR l_i = 1 TO l_ac - 1 #不跟最新的一筆做比較
        IF l_val[l_i].料號 = l_val[l_ac].料號 THEN
            l_val[l_i].數量 = l_val[l_i].數量 + l_val[l_ac].數量
            l_val[l_i].金額 = l_val[l_i].金額 + l_val[l_ac].金額
            l_val[l_i].稅額 = l_val[l_i].稅額 + l_val[l_ac].稅額
            CONTINUE FOREACH
        END IF
    END FOR
    LET l_ac = l_ac + 1
END FOREACH

如果你能改SQL語法,那就用以下的方式
(以你回覆的範例來說)

DEFINE l_ohb DYNAMIC ARRAY OF RECORD
    ohb01    LIKE ohb_file.ohb01, 
    ohb04    LIKE ohb_file.ohb04, 
    ohb30    LIKE ohb_file.ohb30, 
    ohb912   LIKE ohb_file.ohb912, 
    ohb14    LIKE ohb_file.ohb14
END RECORD  
LET l_sql = "SELECT ohb01,ohb04,ohb30,SUM(ohb912),SUM(ohb14) FROM ohb_file WHERE ohb01='",條件一,"' AND ohb30='",條件二,"' GROUP BY ohb01,ohb04,ohb30;"

PREPARE p1_prepare FROM l_sql
DECLARE p1_cur CURSOR FOR p1_prepare
LET l_ac = 1
FOREACH p1_cur INTO l_ohb[l_ac].*
    LET l_ac = l_ac + 1
END FOREACH
carry1246 iT邦新手 5 級 ‧ 2021-04-21 13:49:39 檢舉

我用修改的測試,我發現第三筆依舊會執行,而且也是跑得出值
還是正常來說其實都是會跑值出來?

carry1246 iT邦新手 5 級 ‧ 2021-04-21 15:35:13 檢舉

https://ithelp.ithome.com.tw/upload/images/20210421/201326273Q5sG1uhRh.jpg
我看了一下其他支可以做到FOREACH時 只會讓相同的跑出一筆出來
是因為加了這個嗎?我進DEBUG時,看到他執行第三筆相同時會自己跳出FOREACH,想問是因為這段的關係嗎?

SQLCA.SQLCODE 是Oracle的SQL結果狀態碼,
你可以用Watched看一下值是什麼,再找一下代碼表代表的意思,
=0:正確
-1:錯誤
還有很多,要看狀態碼是多少,才知道他為什麼會在第三筆相同資料的時候跳出迴圈。

carry1246 iT邦新手 5 級 ‧ 2021-04-22 09:01:10 檢舉

https://ithelp.ithome.com.tw/upload/images/20210422/20132627V98QqZk1Py.jpg
當我試著將SQL 修改我發現我抓出的都是空
像我若SELECT 五個並且其中一個是 SUM 就抓不出
一定都要下 select * from ohb_file
還是那個select 必須要所有欄位名稱都要進去?

by2048 iT邦新手 1 級 ‧ 2021-04-22 09:19:33 檢舉

select ohb_file.* 是給 into l2_ohb.*
照您上面的寫法,要into 給l2_ohb.ohb04,l2_ohb.ohb912,l2_ohb.ohb14 三欄

看一下你的l2_ohb 這個RECORD設定了幾個欄位,然後型別是不是符合ohb04,ohb912,ohb14,型別跟長度都會影響能不能接到值。
FOREACH那邊下中斷點,並監視STATUS的值,也是Debug的好方法

carry1246 iT邦新手 5 級 ‧ 2021-04-22 15:14:51 檢舉

如果RECORD 是 l2_ohb RECORD LIKE ohb_file.*
就會產生接值異常嗎?

會喔,因為INTO 是照著RECORD的順序,一個一個塞入,
你如果Debug只看l2_ohb.ohb04,l2_ohb.ohb912,l2_ohb.ohb14,就只有(null),但其實他把值塞進l2_ohb.ohb01,l2_ohb.ohb02,l2_ohb.ohb03了

carry1246 iT邦新手 5 級 ‧ 2021-04-23 14:34:39 檢舉

宣告也是用連續宣告
不能單單record

carry1246 iT邦新手 5 級 ‧ 2021-04-27 07:55:48 檢舉

結果用兩種寫法都無法正確地執行...
結果是我SQL寫法寫錯...導致抓不到值,我後來是改變SQL語法搞定的,您要發一篇那個修改的那個 我好讓他為最佳答案

你可能要提供一下你的程式碼跟Debug的結果,不然很難幫你...

carry1246 iT邦新手 5 級 ‧ 2021-04-27 13:37:10 檢舉

已經解決了,第一段的FOREACH 已經搞定,就是你的修改SQL語法那邊我發現我有條件下錯,導致空值。
當我用第二個FOREACH中有一個條件是 等於第一串FOREACH的值時有可能會變成NULL嗎?

使用第一層FOREACH的結果當作第二層FOREACH的條件也是可以的,但不太懂你說第二個FOREACH有可能會變成NULL的意思?

carry1246 iT邦新手 5 級 ‧ 2021-04-29 15:28:10 檢舉

都搞定了,後來寫錯了。
然後可能是版本不同,您的DEFINE方式我不能那樣寫

0
by2048
iT邦新手 1 級 ‧ 2021-04-15 08:41:33

sql 決定 FOREACH 的內容
所以sql指令對了,結果就對
select 單號,發票號,料號,sum(數量),sum(金額),sum(稅額) from table
group by 料號,單號,發票號
但不知版大是用在報表還是資料處理
如在報表還可以用別的方法
select 單號,發票號,料號,數量,金額,稅額 from table
AFTER GROUP sr.料號
print 單號,
發票號,
料號,
GROUP SUM(sr.數量),
GROUP SUM(sr.金額),
GROUP SUM(sr.稅額)

PS 依本例在同一張單直接修改原始資料就好了,如想不同單合併才會用到這個方法

carry1246 iT邦新手 5 級 ‧ 2021-04-15 09:11:56 檢舉

我用在處理資料
意思是,一開始的 LET sql= ...
這串決定我的資料顯示嗎?

by2048 iT邦新手 1 級 ‧ 2021-04-15 11:11:18 檢舉

是的,這是屬於SQL語言的用法
FOREACH 可以是一筆筆帶出來處理,判斷 單號,發票號,料號跟下一筆相同時數量,金額,稅額做累加,不過這也要SQL語法先配合將料號,單號,發票號做ORDER BY 排序後才做得到

我要發表回答

立即登入回答