ใช้ Last ใน Query เมื่อนำมาUnion แล้วข้อมูลเปลี่ยน
กระทู้เก่าบอร์ด อ.Yeadram

 4,031   17
URL.หัวข้อ / URL
ใช้ Last ใน Query เมื่อนำมาUnion แล้วข้อมูลเปลี่ยน

ผมทำ Query1 โดย Group By และใช้ Last ในฟิลด์ชข้อมูลที่ต้องการ
ค่าที่ออกมาเป็นค่าหนึ่งซึ่งถูกต้องแล้ว
ผมทำ Query2 โดยดึงข้อมูลจากคนละตารางกันแล้วทำหัวฟิลด์ให้เหมือนกัน
และฟิลด์เท่ากัน เพื่อจะเอามา Union กัน

และผมก็ทำ Query Union แต่ ข้อมูลที่ Last ใน Query1 มันกับเป็นข้อมูลอื่นที่ไม่ Last ผมไม่ทราบว่ามันเกี่ยวกับเงื่อนไขอะไรมั่งถึงทำให้ค่ามันเปลี่ยน และควรจะทำอย่างไรครับ

17 Reply in this Topic. Dispaly 1 pages and you are on page number 1

1 @R15513
ใน Query นึง ที่มาจากการ เชื่อมต่อหลายตาราง ถ้าเรา Last ฟิลด์นึง มันหมายความว่า Last ทุกฟิลด์หรือไม่

จากการทดลอง พอเปลี่ยน ข้อมูลจากตาราง ลงใน Query ค่า Last มันก็เปลี่ยนเหมือนกัน

แบบนี้ ถ้านำมา Union กัน อาจทำให้ค่าที่ Last เปลี่ยนได้

เลยทดลอง ลบฟิลด์ ออกหมด เหลือ 2 ฟิลด์ คือ ฟิลด์ที่เป็นคีย์ กับฟิลด์ที่เป็นค่า Last
สรุปว่ามันก็ยังเปลี่ยน แก้ไม่ถูกเลยคราวนี้
2 @R15514
SELECT qDepositBalance.ID_member, qDepositBalance.fname, qDepositBalance.LoanID, qDepositBalance.DepositAccount AS PromisNo,
qDepositBalance.Loan_st, Co_belong.belongname, Co_belong.belongID FROM (qDepositBalance INNER JOIN Member ON qDepositBalance.ID_member = Member.ID_member)
INNER JOIN Co_belong ON Member.belong = Co_belong.belongID;

UNION SELECT Member.ID_member, [title] & [fullname] AS fname, Loan_st.LoanID, Loan_st.PromisNo, Loan_st.Loan_st, Co_belong.belongname, Co_belong.belongID
FROM (Loan_st INNER JOIN Member ON Loan_st.ID_member = Member.ID_member) INNER JOIN Co_belong ON Member.belong = Co_belong.belongID
UNION SELECT share.ID_member, [title] & [fullname] AS fname, 311101 AS LoanID, '' AS PromisNo, share.share_all, Co_belong.belongname, Co_belong.belongID
FROM (share INNER JOIN Member ON share.ID_member = Member.ID_member) INNER JOIN Co_belong ON Member.belong = Co_belong.belongID;


อักษรสีแดงดึงมาจาก Query นี้

SELECT Deposit.ID_member, Deposit.DepositAccount, Last(Deposit.Balance) AS Loan_st, [title] & [fullname] AS fname, 214101 AS LoanID
FROM Member INNER JOIN Deposit ON Member.ID_member = Deposit.ID_member
GROUP BY Deposit.ID_member, Deposit.DepositAccount, [title] & [fullname], 214101;


ซึ่ง Query ล่างนี้แสดงค่าที่ถูกต้อง
3 @R15547
Query Union นอกจาก ใช้ คำว่า Union คั้นระหว่าง SQL แล้วยังมี เทคนิกอะไรอีกมั้ยครับ ที่พอรู้ก็ลองหมดแล้ว
4 @R15551
- "พอเปลี่ยน ข้อมูลจากตาราง ลงใน Query" ตรงนี้หมายถึงยังไงครับ
- ควรใช้ Min( ) หรือ Max( ) มากกว่า Last( ) ครับ
5 @R15552
พบข้อสังเกตุอีกอย่างหนึ่งแปลก
พอรับ Query ที่ยังไม่ Union กัน โดยกรองเฉพาะตัวที่เลือก ค่าที่ได้มันถูก
แต่พอรันโดยไม่กรอง(ไม่ได้ใส่เงื่อนไข) แล้วไปไลดูมันออกมาอีกค่าหนึ่ง
แสดงว่ามันเกี่ยวกับการใส่เงื่อนไขด้วย
6 @R15553
ผมต้องการค่าสุดท้ายครับ ลองใช้ max มันก็ไม่ได้ครับ
ตารางนี้ เก็บข้อมูลลักษณะนี้ครับ

ชนิด    วันที่    รับ จ่าย คงเหลือ
A           1       2      0        2
B           1       1      0        1
C           2       2      0        2
A           2       0      1        1   

ฟิลด์คงเหลือ Data type เป็น Number

ผมทำ Query หาว่า A คงเหลือเท่าไหร่ โดย Group By ตรงคงเหลือ
ผมเลือกเป็น Last ค่าที่ออกมาก มันเป็น 1 แต่พอ นำไปทำ Query Union
มันกลับออกเป็น 2 ประมาณนี้ครับ ล่าสุดลอง Max ก็ไม่ได้
7 @R15555
เคยเข้าใจว่า ถ้าเรานำตารางมาทำ Query แล้วเมื่อเรา Group By
บางตัวเรา min บางตัวเราใช้ Last ข้อมูลใน เรคคอดนั้น จะสัมพันธ์กัน
แต่จากประสบการครั้งนี้ ไม่ใช่แล้ว
8 @R15556
ไม่ทราบว่า เป็นเรื่องเดียวกับการ ยกมา-รับ-จ่าย-คงเหลือ หรือเปล่านะครับ
แต่ยกตัวอย่างใหม่ให้ดูอีกแบบแล้วกันนะครับ สมมุติผมมีตารางชื่อ Table1 ดังนี้:

aName     aDate       Import   Export
A           1/3/2013      2           0
B           1/3/2013      1           0
B           2/4/2013                  1
A           2/4/2013                  1

เขียนคิวรี่สรุป
ชื่อสินค้า นำเข้าทั้งหมด ส่งออกทั้งหมด ยกมาสะสม นำเข้าเดือนนี้ ส่งออกเดือนนี้ คงเหลือ
A               2                 1               2             0               1            1
B               1                 1               1             0               1            0

อธิบาย
(นำเข้าทั้งหมด) คือ รวมค่า Import ทั้งหมดที่มีในตาราง
(ส่งออกทั้งหมด) คือ รวมค่า Export ทั้งหมดที่มีในตาราง
(ยกมาสะสม) คือ ค่าคงเหลือสะสมที่ผ่านมาทั้งหมดยกเว้นเดือนปัจจุบันที่เรียกดู
(นำเข้าเดือนนี้) คือ รวมค่า Import เฉพาะเดือนปัจจุบันที่เรียกดู หากไม่มีจะเป็น 0
(ส่งออกเดือนนี้) คือ รวมค่า Export เฉพาะเดือนปัจจุบันที่เรียกดู หากไม่มีจะเป็น 0
(คงเหลือ) คือ สรุปยอดคงเหลือทั้งหมดที่มีอยู่ในคลังสินค้า

โดยผมเขียน SQL ดังนี้ครับ:
SELECT A.aName AS ชื่อสินค้า, Sum(Nz([Import])) AS นำเข้าทั้งหมด, Sum(Nz([Export])) AS ส่งออกทั้งหมด, (SELECT NZ(Sum([Import])) - NZ(Sum([Export])) FROM Table1 AS B WHERE A.[aName] = B.[aName] AND B.[aDate] < DateSerial(Year(Date()),Month(Date()),1)) AS ยกมาสะสม, Int((SELECT Nz(Sum([Import]),0) FROM [Table1] WHERE [aName] = A.[aName] AND [aDate] >= DateSerial(Year(Date()),Month(Date()),1))) AS นำเข้าเดือนนี้, Int((SELECT Nz(Sum([Export]),0) FROM [Table1] WHERE [aName] = A.[aName] AND [aDate] >= DateSerial(Year(Date()),Month(Date()),1))) AS ส่งออกเดือนนี้, [ยกมาสะสม]+[นำเข้าเดือนนี้]-[ส่งออกเดือนนี้] AS คงเหลือ
FROM Table1 AS A
GROUP BY A.aName
ORDER BY A.aName;

หากพอจะตรงตามความต้องการบ้าง ก็ลองสร้างตารางตามผมดูก่อน แล้วใส่ข้อมูลทดสอบตัวเลขดูว่าได้ตามที่ต้องการหรือไม่ ปรับใช้ดูครับ หวังว่าคงตอบโจทย์ได้บ้างนะครับ
9 @R15558
คนละโปรแกรมเลยครับ อาจารย์ TTT
อันนี้มีฟิลด์คงเหลือเก็บค่าในตารางแล้วครับ
เพียงแต่ค่าที่เก็บมันจะ จัดการ บวกลบ มาแล้ว
ผมแค่ต้องการทำ Query ให้ได้ค่า คงเหลือ ค่าสุดท้ายครับ
แต่เมื่อทำ Query แล้ว มันไม่ได้ค่าสุดท้าย มันกลับไปได้
ค่าใดค่าหนึ่งครับ

ส่วนที่อาจารย์มาตอบเมื่อวาน ใช้ได้ดีเลยครับ กำลังคิดว่าจะ
เปลี่ยน Harddisk เป็นแบบ SSD จะได้คำนวนได้เร็วขึ้นครับ

10 @R15723
ในคิวรี่ เดียวกัน ถ้า ใส่เงื่อนไขเลือก Member มา 1 คน ผลที่ออกมาถูก ต้อง
แต่พอ เอาเงื่อนไขออก แล้ว ไล่ดู จากทุกสมาชิก กลับเป็นอีกค่า หนึ่ง Last นี่มันใช้ยากจริง
มีวิธีที่ได้ค่าสุดท้าย ที่ แปะๆ มั้ยครับ
11 @R15724
ผมเข้าใจว่าการที่ใช้ฟังก์ชั่น First หรือ Last ไม่สามารถใช้ในกรณีของการนำตารางมา Union เพราะการบันทึกเรคคอร์ดล่าสุดของระบบโปรแกรม MS Access ผมเข้าใจว่ามันจะบันทึกเป็นแค่ค่าตัวเลขเพียงอย่างเดียว เหมือนกับการทำ Autonumber ของเรานั่นแหละครับ ระบบมันก็ทำของมันซ่อนอยู่ในตารางระบบ (จะเปรียบเทียบกับ Windows ก็เหมือนการทำตาราง FAT) พอเราเรียก Last โปรแกรมมันก็จะไปค้นค่า ID ในระบบที่มากที่สุดออกมา แต่พอเรานำสองตารางมารวมกัน คราวนี้ค่า ID ในระบบจะใช้ไม่ได้แล้ว เพราะต่างตารางก็มีค่า ID ของตัวเอง ซึ่งมากน้อยอย่างไรมันก็ไม่สามารถใช้เทียบกันได้ เพราะมันต่างกรรมต่างวาระ กันเสียแล้ว เท่าที่เคยสังเกตุ หากเป็นอย่างนี้ค่าในฟังก์ชั่น First จะกลายเป็นค่า Min และค่า Last จะกลายเป็นค่า Max ไปครับ
- คราวนี้จะทำอย่างไรหากต้องการ Last และต้อง Union กันด้วย อันนี้อยากครับ เท่าที่ผมคิดได้คือต้องคิดตั้งแต่การออกแบบมาแล้วว่า เราต้องนำตารางกลุ่มนี้มา Union กัน แล้วผมจะเพิ่มฟิลด์สำหรับเก็บค่า Now() ไว้ ให้กับตารางเหล่านั้นสำหรับการบันทึกเรคคอร์ดใหม่ลงตารางทุกครั้ง นั่นแหละครับไว้เทียบค่า First กับ Last แม่นยำที่สุด
12 @R15733
ต่อให้อีกนิดนะครับ กรณีคำถาม
Last นี่มันใช้ยากจริง มีวิธีที่ได้ค่าสุดท้าย ที่ แปะๆ มั้ยครับ
- ผมไม่รู้ว่าคุณจะหาแบบที่ผมเข้าใจหรือไม่ คือ สมมุติผมมีตารางชื่อ Table1 ดังนี้:

ชนิด    วันที่    รับ จ่าย คงเหลือ
A           1       2      0        2
B           1       1      0        1
C           2       2      0        2
A           2       0      1        1

- ผมต้องการหาค่า คงเหลือ ชนิดที่เป็นค่า A เรคคอร์ดล่าสุดเสมอ หากเป็นคิวรี่ผมจะใช้ซับคิวรี่เขียนแบบนี้ครับ
(SELECT Last([คงเหลือ]) FROM Table1 WHERE [ชนิด] = "A")

จะ Return ค่าในฟิลด์คงเหลือมาให้เป็น 1

- หากมีการใส่ข้อมูลเพิ่มเข้าไปในตาราง เช่น
ชนิด    วันที่    รับ จ่าย คงเหลือ
A           1       2      0        2
B           1       1      0        1
C           2       2      0        2
A           2       0      1        1
A           0       0      0        0
B           2       0      1        5

จะ Return ค่าในฟิลด์คงเหลือมาให้เป็น 0

-จะใช้คำสั่งซับคิวรี่เป็นเงื่อนไขใน Criteria
-ใส่เป็นฟิลด์ใหม่ในคิวรี่
- ค่าที่ได้จะถูกต้องเสมอ

ไม่รู้ตรงกับปัญหาหรือไม่นะครับ แต่ฝากไว้ว่าการใช้ First() หรือ Last() หมายถึงเรคคอร์ดที่ถูกสร้างขึ้น แรกสุด หรือ หลังสุด หลายคนอาจเข้าใจสับสนว่าหมายถึงค่าในฟิลด์ที่ใส่เข้าไปในฟังก์ชั่น การใส่ Last(ชื่อฟิลด์) หมายถึง ให้ส่งค่าในฟิลด์ชื่อนี้จากเรคคอร์ดที่มีการสร้างไว้หลังสุด(ใหม่สุด) กลับมา ชื่อฟิลด์ที่ใส่จึงไม่ใช้เงื่อนไขหรือใช้ค่าของฟิลด์ไปประมวลผลใดๆนะครับ ต้องเข้าใจหลักของฟังก์ชั่นนี้ก่อนใช้
13 @R15734
อาจารย์ TTT ถ้าวันเดียวกัน มี 2 เวลาหล่ะ
14 @R15735
หมายถึงกรณีอะไรครับ
15 @R15736
ชนิด    วันที่    รับ จ่าย คงเหลือ
A           1       2      0        2
B           1       1      0        1
C           2       2      0        2
A           2       0      1        1
A           0       0      0        0
B           2       0      1        5
B           2       0      1        4

อย่าง B สุดท้ายครับ วันเดียวกันจ่าย 2 ครั้ง
มันจะออกมา Last มั้ย แต่ผมว่า รอทำดูเลยดีกว่า
แล้วมาบอกอาจารย์
16 @R15737
แสดงว่ายังไม่เข้าใจอะครับ
ไม่เกี่ยวกับว่าวันไหนครั้งไหน Last() คือ เรคคอร์ดสุดท้ายที่สร้างขึ้น ค่าเดียวเท่านั้น (และก็ไม่เกี่ยวกับการแก้ไขเรคคอร์ดครั้งสุดท้ายด้วยนะครับ เดี๋ยวจะงงอีกขั้น)

เอางี้ครับให้เห็นภาพรวม จากตัวอย่าง
(SELECT Last([คงเหลือ]) FROM Table1 WHERE [ชนิด] = "A")
คุณว่ามันเหมือนกับฟังก์ชั่นอะไรครับ
เฉลย
DLast("[คงเหลือ]", "Table1", [ชนิด] = "A")
พูดอีกอย่าง (SELECT Last([คงเหลือ]) FROM Table1 WHERE [ชนิด] = "A") ลักษณะแบบนี้มันก็คือ DLast() เวอร์ชั่น SQL นั่นเอง ยังเคยตั้งโจทย์สมมุติ คิดเล่นๆว่า หากใน VBA เค้าไม่ให้ใช้ DLast() แล้ว เราสามารถเขียนฟังก์ชั่นแบบเดียวกับ DLast ใช้เองได้ไง คำตอบคือ

Private Function DLastX(Expr As String, Domain As String, Optional Criteria As String = vbNullString) As String
    Dim rs As DAO.Recordset, SQL As String
    If Criteria & "" = "" Then
        SQL = "SELECT Last(" & Expr & ") As TTT FROM " & Domain
    Else
        SQL = "SELECT Last(" & Expr & ") As TTT FROM " & Domain & " WHERE " & Criteria
    End If
    Set rs = CurrentDb.OpenRecordset(SQL)
    DMaxX = rs!TTT
    rs.Close
    Set rs = Nothing
End Function

จะได้ค่าเหมือนกันเป๊ะ ฉนั้น DMax, DMin, DFirst, DLookup หากต้องการเขียนแบบซับคิวรี่ก็เขียนแบบนี้เหมือนกัน ส่วน Last() มันก็คือฟังก์ชั่นแบบใช้งานตรงๆ ไม่มีเงื่อนไขในหลายกรณีมันจึงไม่ยืดหยุ่น จะใช้หาค่าอย่างที่ต้องการไม่ได้เลย ยิ่งในกรณีหากต้องแบ่ง Group by มันจะยิ่งไม่มีผลเท่าไร เพราะมันจะมองทุกกลุ่มเป็น Last() หมด
ทั้งหมดนี่นอกเรื่องไปหน่อย แต่ให้อ่านสำหรับคนที่ยังคิดการใช้ซับคิวรี่ไม่ออกจะได้เห็นภาพรวมมากขึ้น ในการใช้รวมกับฟังก์ชั่นอื่นๆ นี่เป็นกรณีนึงที่เห็นว่าอธิบายแล้วน่าจะเห็นภาพ ประมาณนี้ครับ
17 @R17455
ค้นหากระทู้เก่าๆ เพิ่งเห็นอาจารย์ TTT มาตอบ
ผมลองทำตามกระทู้ R15733 โดยใช้ซับคิวรี
ผลออกมา ก็ไม่ได้ Last จริงอยู่ดีครับ และ ระบุ WHERE แบบนั้น มันจะได้แต่
สินค้า A มาทุกเรคคอดเลยครับ

มากระทู้สุดท้าย R15737 ฟังชันนี้ DLastX ผมแทนค่าไม่ถูกครับ

Expr = อะไรครับ
Domain = อะไรครับ
Optional Criteria = อะไรครับ

ขอบพระคุณอาจารย์ TTT ที่มาตอบ
@ ประกาศใช้งานเว็บบอร์ดใหม่ => บอร์ดเรียนรู้ Access สำหรับคนไทย
แล้วจะใส่ลิ้งอ้างอิงมาที่โพสต์เก่านี้หรือไม่ก็ตามสะดวกครับ
Time: 0.2033s