การใช้ Group By
กระทู้เก่าบอร์ด อ.Yeadram

 8,748   28
URL.หัวข้อ / URL
การใช้ Group By

คือผมเขียนคิวรี่โดยใช้คำสั่ง group by
select proid,qty,Sum(amount) as sumamount
from inv_stockcarddetail
group by proid ;
ประมาณนี้นะครับ ผมสงสัยว่าทำไม โปรแกรมมันถึงฟ้อง error ตรง qty ว่า you tried to execute a query that does not include the specified expression 'qty' as part of an aggregate function.
แต่ถ้าใส่ sum เข้าไปกลับไม่มีปัญหา หรือว่าต้องใส่อะไรยังไงครับ

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

1 @R03753
ผมขอถามต่ออีกข้อนึงครับว่า เป็นไปได้ไหม ถ้าผมจะหายอดคงเหลือตามที่ผมให้ตัวอย่างข้อมูลมาครับ

no        เงินเข้า             เงินออก               ยอดคงเหลือ                 
1           200                     -                      200
2           500                     -                      700
3              -                    300                    400
4           100                     -                      500
5              -                     500                     0
2 @R03754
เมื่อคุณใช้ group by นั่นหมายถึง คุณต้องการหาผลลัพธ์จากการรวมกลุ่ม ซึ่งผลของมันย่อมเป็นไปได้แค่ 2 ประเภทเท่านั้น คือ ดัวฟิลด์ที่ใช้ในการรวมกลุ่มเอง หรือ ฟังก์ชั่นที่เป็นผลจากการรวมกลุ่มที่เรียกกันว่า Aggregate Function เช่น ผลรวมตามกลุ่ม (Sum()), ค่าสูงสุดตามกกลุ่ม (Max()), ค่าต่ำสุดตามกลุ่ม (Min()) เป็นต้น

ดังนั้น ฟิลด์ qty ไม่ได้เป็นทั้งฟิลด์ที่เป็นเงื่อนไขในการรวมกลุ่ม และไม่ได้เป็นทั้งผลจากฟังก์ชั่นตามที่บอกไปแล้ว มันจึงไม่รู้จะเอาค่าอะไรของ qty มาแสดงให้ได้ ก็เท่านั้นเองครับ
3 @R03755
สมมุติฟิลด์ชื่อ f_no, f_in, f_out จากเทเบิลชื่อ f

SQL Statement ที่ใช้หาผลลัพธ์ตามที่ต้องการคือ

SELECT f1.f_no, f1.f_in, f1.f_out, (select sum(f2.f_in - f2.f_out) from f as f2 where f2.f_no <= f1.f_no) AS balance
FROM f AS f1
ORDER BY f1.f_no, No
4 @R03758
เรื่องที่ 1. Group by
ถ้าผมต้องการให้แสดง qty ด้วย อย่างนี้ผมต้องทำอย่างไรครับ

5 @R03760
ก็ต้องถามตัวเองว่า qty นั้นเป็นผลของการรวมกลุ่มหรือไม่ ถ้าเป็น เป็นผลมาจาก Aggregate Function ไหน    หรือว่าเราจะรวมกลุ่มตาม prodid และ qty ด้วย หมายถึงสินค้าเดียวกัน และจำนวนขายเท่ากัน ก็รวมเป็นกล่มนึง

เมื่อถามตัวเองได้คำตอบแล้ว คุณก็จะตอบคำถามตัวเองได้โดยปริยาย
6 @R03817
เอ่อ อาจารย์ครับ ผมขอถามเรื่องฐานข้อมูลหน่อยครับ
คือฟิลด์ no ตอนแรกผมตั้งเป็น text ไว้ แต่ทีนี้ตามโค๊ตนี้มันต้องมีการรันเลขที่ไปเรื่อยๆเพื่อเช็คค่าก่อนหลัง ผมเลยไปแก้ที่ mysql ให้ฟิลด์ no เป็น auto increment
แต่ไม่รู้ทำไมมันไม่ยอมให้สร้างครับ error ตลอด ผลลองสร้าง table ใหม่เลยแล้วลองตั้ง auto increment มันก็ไม่ได้อยู่ดีครับ

Error

SQL query:

ALTER TABLE `inv_stockcarddetail` CHANGE `no` `no` INT( 11 ) NOT NULL AUTO_INCREMENT

MySQL said: Documentation
#1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key
7 @R03820
อีกอย่างนึงครับผมลองเทสรายงานยอดคงเหลือดู
ตอนแรกไม่มีปัญหาอะไรครับ แต่พอรันอีกครั้ง เปลี่ยนช่วงวันที่ มันกลับดึงเลขจากไหนมาคำนวณก็ไม่ทราบครับ

โดยคิวรี่ที่ผมเขียนจะดึงข้อมูลมาจากช่วงวันที่ที่เลือกครับ แล้วใช้ no ตรวจสอบอันไหนมาก่อนหลังครับ
8 @R03821
- ผมไม่ชำนาญการใช้คำสั่งพวก DDL ครับ ก็ไม่รู้ว่าคำสั่ง ALTER TABLE นั้นถูกต้องหรือไม่ พอไปค้นใน Google ก็เห็นมีบางคนแนะนำคำสั่งนี้

alter table ชื่อเทเบิล add ชื่อพิลด์ int(11) primary key auto_increment not null

- อีกปัญหาก็คงเกี่ยวกับช่วงวันที่แหล่ะครับ ผมก็ไม่เคยเรียกใช้ผ่าน ODBC ด้วยเช่นกัน ปัญหาที่ว่า ผมหมายถึง เราจะต้องส่งวันที่ในรูปแบบอะไรไปให้ ODBC ดี และใช้สัญญลักษณ์อะไรเป็น delimited เช่น ข้อกำหนดของ ODBC ต้องส่งเป็น #เดือน/วัน/ปี# เท่านั้นหรือไม่ ตรงนี้ต้องลองไปอ่าน Help ของ ODBC ดูครับ

ถ้าใครพอทราบก็ช่วยตอบด้วยครับ
9 @R03822
ลองเอา คิวรี่ ที่ดึงข้อมูลมาแสดงให้ดูหน่อย
10 @R03824
SELECT f1.invoiceid, f1.invoicedate, inv_products.name, inv_products.description, inv_products.unit, f1.quantity, f1.number, f1.moneyin, f1.moneyout, (select sum(f2.moneyin - f2.moneyout) from inv_StockCardDetail as f2 where f2.number <= f1.number ) AS balance, f1.comment
FROM inv_StockCardDetail AS f1 INNER JOIN inv_products ON f1.proid = inv_products.name
WHERE (((f1.invoicedate)>=[Forms]![CC-Sales Reports Dialog]![FromDate] And (f1.invoicedate)<=[Forms]![CC-Sales Reports Dialog]![ToDate]))
ORDER BY f1.number;
11 @R03825
ผมเชื่อว่า

WHERE (((f1.invoicedate)>=[Forms]![CC-Sales Reports Dialog]![FromDate] And (f1.invoicedate)<=[Forms]![CC-Sales Reports Dialog]![ToDate]))

นี่แหล่ะคือตัวปัญหา เพราะ FromDate และ ToDate ยังไงมันก็คือ Textbox ค่าที่ได้ก็คือ Text ไม่ใช่ข้อมูลประเภท Date มันต้องเกิดการแปลงให้เองอย่างอัตโนมัติ ซึ่งอาจจะแปลงถูกแปลงผิดก็ได้ เช่นถ้า FromDate บนหน้าจอเป็นค่า 1/10/2009 ถามหน่อยว่า มันจะรู้ได้อย่างไรว่าเป็น เดือน 10 หรือ เดือน 1 กันแน่ ทางที่ดีที่สุด ถ้าเรารู้ว่าข้อกำหนดในการเขียนเพื่อส่งไป ODBC นั้น เป็นรูปแบบไหน เราก็เขียนรูปแบบนั้นตรงๆไปเลยจะดีกว่าครับ
12 @R03833
คือเรื่อง odbc นี่ผมก็ไม่ค่อยเข้าใจอะครับ
เพราะผมมาทำต่ออีกทีครับ คือผมเพิ่มมาใช้ access งานแรกเลยครับ
แล้วทีนี้ผมต้องแก้ปัญหายังไงครับ
13 @R03834
MySQL ต้องส่งค่าวันที่ เข้าไปในรูปแบบ yyyy-mm-dd และส่วนใหญ่ พวกฐานข้อมูลระดับใหญ่มักจะใช้แบบนี้กันทั้งนั้น

ถ้าปัญหามันเป็นอย่างที่ อ.สันติสุขว่า คุณก็น่าจะปรับรูปแบบของ วันที่ให้อยู่ในรูปแบบที่ MySQL ยอมรับได้ซะก่อน ก่อนจะส่ง statement เข้าไป

dim fDate as string
dim tDate as string
fDate = format([Forms]![CC-Sales Reports Dialog]![FromDate],"yyyy-mm-dd")
tDate = format(Forms]![CC-Sales Reports Dialog]![ToDate], "yyyy-mm-dd")

- เขียน statement ตามปกติ เมือถึง where ก็ใช้
WHERE (f1.invoicedate Between '" & fDate & "' AND '" & tDate & "')"
14 @R03835
ลองแบบที่เรียกใช้กับฐานข้อมูลของ Access เองดูก่อนครับ อาจเหมือนกัน
ก่อนอื่นเนื่องจากเพราะการตีความของวันที่ที่มันไม่แน่ใจนั้น มันจะใช้รูปแบบที่กำหนดใน Control Panel    ดังนั้นไปที่ Control Panel > Regional and Language Options > Regional > Options > Customize > Date > Short Date Format ให้เป็น dd/mm/yyyy ต่อมาในเท็กซ์บ๊อกส์ที่รับค่าวันที่ ไม่ต้องกำหนด InputMask แต่กำหนด Format ให้เป็น Short Date ดังนั้นไม่ว่าคุณจะป้อนเป็น 1/10/2009 หรือ 1-10-2009 หรือ 1-oct-2009 หรือ 1 oct 2009 หรือ 1/11/9 มันก็จะพยายามแปลงให้เห็นเป็น 1/11/2009 ตาม Short Date Format ที่เราได้กำหนดไว้ก่อนหน้านี้ และเราก็จะมั่นใจได้ว่ามันคือวันที่ 1 ตุลาคม 2009 ไม่ใช่เป็นวันที่ 10 มกราคม 2009

เข้าใจว่าคุณสร้างเป็น Query object ใช่ไหม ไม่ใช่เป็นคำสั่ง SQL Statement ใน VBA   ดังนั้นก็ลองสั่งให้ทำงานได้เลย

ถ้ายังไม่ได้ยังไงก็มาคุยกันอีกที
15 @R03851
อาจารย์ครับ
พอรันครั้งแรก ก็ไม่มีปัญหาอะไรครับคำนวณถูกต้อง แต่พอเปลี่ยนวันที่ ก็ผิดพลาดเลยครับ คือผมเดาว่า เหมือนกับมันจำจำนวนเก่าไว้แล้วเอามาบวกอีกทีนึงนะครับ
16 @R03853
แล้วก็ผมขอถามหน่อยครับว่า
(select sum(f2.moneyin - f2.moneyout) from inv_StockCardDetail as f2 where f2.number <= f1.number ) AS balance
ตรง where f2.number แล้ว f2.number นี่แทนค่าอะไรหรอครับ
17 @R03854
select sum(f2.moneyin - f2.moneyout)
เลือก ผลรวมของผลต่างจากมูลค่าเข้าและออก

from inv_StockCardDetail as f2
จากเทเบิล inv_StockCardDetail โดยใช้ชื่อเล่นว่า f2

where f2.number <= f1.number
โดยเลือกเฉพาะเรคอร์ดที่ฟิลด์ number จาก f2 นี้ มีค่าน้อยกว่าฟิลด์เดียวกันที่กำลังจะแสดงผลในแต่ละบบรรทัด ซึ่งคือ f1.number นั่นเอง
18 @R03856
แล้วอาจารย์พอจะทราบมั้ยครับว่าทำไมพอรันครั้งแรก ก็ไม่มีปัญหาอะไรครับคำนวณถูกต้อง แต่พอเปลี่ยนวันที่ ก็ผิดพลาดเลยครับ คือผมเดาว่า เหมือนกับมันจำจำนวนเก่าไว้แล้วเอามาบวกอีกทีนึงนะครับ

ผมมีแนวคิดว่าจะเปลี่ยนมาเขียน vba แต่ก็ไม่เก่งอีก
19 @R03857
- ช่วงวันที่ในการรันครั้งแรกคือค่าอะไร และครั้งที่สองคือค่าอะไร
- ฟิลด์ invoicedate ในเทเบิล มี data type เป็นอะไร
20 @R03858
- ช่วงวันที่ในการรันครั้งแรกคือค่าอะไร และครั้งที่สองคือค่าอะไร
------ ครั้งแรก 12/10/2552 - 12/10/2552
------ ครั้งที่สอง 13/10/2552 - 13/10/2552
ทีนี้พอผมกลับไปเลือกเป็นวันที่ 12/10/2552 - 12/10/2552 ก็ไม่ได้อยู่ดีครับ

- ฟิลด์ invoicedate ในเทเบิล มี data type เป็นอะไร
------ date
@ ประกาศใช้งานเว็บบอร์ดใหม่ => บอร์ดเรียนรู้ Access สำหรับคนไทย
แล้วจะใส่ลิ้งอ้างอิงมาที่โพสต์เก่านี้หรือไม่ก็ตามสะดวกครับ
Time: 0.2783s