กระทู้เก่าบอร์ด อ.Yeadram
4,904 3
URL.หัวข้อ /
URL
ปัญหาจากกการนำ Query มาซ้อนกัน [Query is too omple
สวัสดีครับ
ผมมีปัญหาเรื่องการใช้ Query มาซ้อนกันหลายๆ อันน่ะครับ ตอนนี้เจอปัญหาใช้คำสั่ง UNION จาก Query ต่างๆ ที่สร้างไว้ แล้วเกิดข้อความขึ้นดังนี้ครับ "Query is too omplex." คาดว่าอาจเป็นเพราะแต่ละ Query เขียนโค๊ตยาวด้วยน่ะครับ อยากจะให้ท่านผู้รู้ให้คำแนะนำทีนะครับ
ผมเขียนโปรแกรมเกี่ยวกับการจัดการทัวร์ครับ
โดยมีการเก็บข้อมูลรายละเอียดต่างๆ ของแต่ละทัวร์ แยกชิ้นส่วนแต่ละอย่างออกไป เช่น โรงแรม, การเดินทาง, ทัวร์, ไกด์, กิจกรรม
ผมต้องการจัดทำรายการพวกนี้ไว้เป็นกลุ่มๆ เป็น Package เพื่อที่จะหาราคา หรือทำ Booking ให้กับลูกค้าได้อย่างรวดเร็ว และสามารถ Export ราคานี้ส่ง Agency อื่นๆ ที่ติดต่อกับเราด้วย ดังนั้น ตารางที่ออกมาจะได้เป็น
Package Name | Group | Season | 1 | 2 | 3 | 4 | ... | 40 (ราคาตั้งแต่ 1 - 40 คน เป็นราคาต่อคน)
แต่ก่อนถึงขั้นตอนนั้น ผมต้องนำสินค้าแต่ละรายการ แจกแจกข้อมูลราคา แยกไปตามช่องของจำนวนให้ถูกต้อง
จากนั้นจึงรวมข้อมูลนั้น (UNION) มารวมกัน ข้อมูลที่จะได้จะเป็นข้อมูลของสินค้าทุกๆ รายการที่เลือกไว้ลงใน Package (ปัญหาเกิดตรงนี้)
และผลจะใช้ Sum เพื่อหาผลรวมของราคาอีกที
ตัวอย่างตารางเก็บข้อมูลดิบอย่างคราวๆ
สินค้าประเภทกิจกรรม
Product Name | Description | Supplier | Min | Max | Cost | Inc. VAT | Flag
อธิบาย
Name คือชื่อสินค้า
Description คือ คำอธิบายสินค้า
Supplier คือ ผู้จำหน่าย, ตัวแทนจำหน่าย
Min คือ จำนวนต่ำสุดที่ใช้ราคานี้ได้
Max คือ จำนวนสูงสุดที่ใช้ราคานี้ได้
Cost คือ ราคา
Inc. VAT คือ มี Vat รวมอยู่หรือไม่ มี 3 ค่า คือ Inc. VAT | Exc. VAT | Vat 0%
Flag คือ ค่า Status ของสินค้า มี 2 ค่า คือ Active | Inactive
ข้อมูลที่ถูกใส่ไว้ในตาราง Package
Package Name | Product Name | Supplier
ข้อมูลที่แสดงราคาใน Package
Package Name | Product Name | Supplier | Min | Max | RealCost | 1-40
โค๊ตตัวอย่างที่แสดงราคาของ 1-40 (ในที่นี้เป็น การเดินทาง)
1: IIf([UseCITSupVeDetail].[privateOrJoin]="Join",[Prices]*1,IIf([UseCITSupVeDetail].[privateOrJoin]="SightVe",IIf(1 Mod [maxCapacity]=0,[Prices]*(1/[maxCapacity]),[Prices]*(Int(1/[maxCapacity])+1)),IIf(1>=[minCapacity] And 1<=[maxCapacity],IIf([fixedOrVar]="Fixed",[Prices],[Prices]*1),0)))
2: IIf([UseCITSupVeDetail].[privateOrJoin]="Join",[Prices]*2,IIf([UseCITSupVeDetail].[privateOrJoin]="SightVe",IIf(2 Mod [maxCapacity]=0,[Prices]*(2/[maxCapacity]),[Prices]*(Int(2/[maxCapacity])+1)),IIf(2>=[minCapacity] And 2<=[maxCapacity],IIf([fixedOrVar]="Fixed",[Prices],[Prices]*2),0)))
.
.
.
40: IIf([UseCITSupVeDetail].[privateOrJoin]="Join",[Prices]*40,IIf([UseCITSupVeDetail].[privateOrJoin]="SightVe",IIf(40 Mod [maxCapacity]=0,[Prices]*(40/[maxCapacity]),[Prices]*(Int(40/[maxCapacity])+1)),IIf(40>=[minCapacity] And 40<=[maxCapacity],IIf([fixedOrVar]="Fixed",[Prices],[Prices]*40),0)))
อธิบายโค๊ต
ถ้า สินค้า เป็นประเภท Join ให้นำราคาคูณ จำนวนคน แต่ถ้าเป็นประเภท SightVe (หมายถึง สินค้าประเภทการเดินทางเป็น join เช่น เรือ ซึ่งราคานับเป็นคันๆ) นำจำนวนคน หาร เพื่อให้ทราบจำนวนเรือที่ใช้ในการเดินทาง และถ้าหากเป็น Private (หลุด IIF) ก็ค้นดูว่า ราคานี้ ควรจะอยู่ตำแหน่งช่องนี้หรือไม่? โดยนำ จำนวนคน เทียบกับ จำนวนต่ำสุด และสูงสุด ของสินค้านี้ที่รองรับ เมื่อเป็น Private ก็ตรวจสอบอีกว่า สินค้านี้เป็นชนิด Fixed หรือ Variable เพื่อที่จะคำนวณราคาได้ถูกต้อง
ตัวอย่างโค๊ตที่แสดงราคานี้ มีจำนวน 7 ตารางๆ ละ 40 Column โดยประมาณ
หากนำมา UNION กัน จะต้องทำอย่างไรครับ ตอนนี้ที่ใช้อยู่คือ
Query1.* FROM Query1 UNION
Query2.* FROM Query2 UNION
.
.
.
Query7 * FROM Query7;
น่ะครับ และมีวิธีทางอื่นอีกไหม? ที่จะทำงานได้ดีกว่านี้ หรือเสถียรภาพกว่านี้
เพราะผมเขียนไปเรื่อยๆ ตอนนี้ มีความรู้สึกว่า Access เริ่มทำงานช้าลง เวลารันโค๊ตที่เกี่ยวกับ ตารางคำนวณพวกนี้
ขอบคุณล่วงหน้านะครับ
ผมมีปัญหาเรื่องการใช้ Query มาซ้อนกันหลายๆ อันน่ะครับ ตอนนี้เจอปัญหาใช้คำสั่ง UNION จาก Query ต่างๆ ที่สร้างไว้ แล้วเกิดข้อความขึ้นดังนี้ครับ "Query is too omplex." คาดว่าอาจเป็นเพราะแต่ละ Query เขียนโค๊ตยาวด้วยน่ะครับ อยากจะให้ท่านผู้รู้ให้คำแนะนำทีนะครับ
ผมเขียนโปรแกรมเกี่ยวกับการจัดการทัวร์ครับ
โดยมีการเก็บข้อมูลรายละเอียดต่างๆ ของแต่ละทัวร์ แยกชิ้นส่วนแต่ละอย่างออกไป เช่น โรงแรม, การเดินทาง, ทัวร์, ไกด์, กิจกรรม
ผมต้องการจัดทำรายการพวกนี้ไว้เป็นกลุ่มๆ เป็น Package เพื่อที่จะหาราคา หรือทำ Booking ให้กับลูกค้าได้อย่างรวดเร็ว และสามารถ Export ราคานี้ส่ง Agency อื่นๆ ที่ติดต่อกับเราด้วย ดังนั้น ตารางที่ออกมาจะได้เป็น
Package Name | Group | Season | 1 | 2 | 3 | 4 | ... | 40 (ราคาตั้งแต่ 1 - 40 คน เป็นราคาต่อคน)
แต่ก่อนถึงขั้นตอนนั้น ผมต้องนำสินค้าแต่ละรายการ แจกแจกข้อมูลราคา แยกไปตามช่องของจำนวนให้ถูกต้อง
จากนั้นจึงรวมข้อมูลนั้น (UNION) มารวมกัน ข้อมูลที่จะได้จะเป็นข้อมูลของสินค้าทุกๆ รายการที่เลือกไว้ลงใน Package (ปัญหาเกิดตรงนี้)
และผลจะใช้ Sum เพื่อหาผลรวมของราคาอีกที
ตัวอย่างตารางเก็บข้อมูลดิบอย่างคราวๆ
สินค้าประเภทกิจกรรม
Product Name | Description | Supplier | Min | Max | Cost | Inc. VAT | Flag
อธิบาย
Name คือชื่อสินค้า
Description คือ คำอธิบายสินค้า
Supplier คือ ผู้จำหน่าย, ตัวแทนจำหน่าย
Min คือ จำนวนต่ำสุดที่ใช้ราคานี้ได้
Max คือ จำนวนสูงสุดที่ใช้ราคานี้ได้
Cost คือ ราคา
Inc. VAT คือ มี Vat รวมอยู่หรือไม่ มี 3 ค่า คือ Inc. VAT | Exc. VAT | Vat 0%
Flag คือ ค่า Status ของสินค้า มี 2 ค่า คือ Active | Inactive
ข้อมูลที่ถูกใส่ไว้ในตาราง Package
Package Name | Product Name | Supplier
ข้อมูลที่แสดงราคาใน Package
Package Name | Product Name | Supplier | Min | Max | RealCost | 1-40
โค๊ตตัวอย่างที่แสดงราคาของ 1-40 (ในที่นี้เป็น การเดินทาง)
1: IIf([UseCITSupVeDetail].[privateOrJoin]="Join",[Prices]*1,IIf([UseCITSupVeDetail].[privateOrJoin]="SightVe",IIf(1 Mod [maxCapacity]=0,[Prices]*(1/[maxCapacity]),[Prices]*(Int(1/[maxCapacity])+1)),IIf(1>=[minCapacity] And 1<=[maxCapacity],IIf([fixedOrVar]="Fixed",[Prices],[Prices]*1),0)))
2: IIf([UseCITSupVeDetail].[privateOrJoin]="Join",[Prices]*2,IIf([UseCITSupVeDetail].[privateOrJoin]="SightVe",IIf(2 Mod [maxCapacity]=0,[Prices]*(2/[maxCapacity]),[Prices]*(Int(2/[maxCapacity])+1)),IIf(2>=[minCapacity] And 2<=[maxCapacity],IIf([fixedOrVar]="Fixed",[Prices],[Prices]*2),0)))
.
.
.
40: IIf([UseCITSupVeDetail].[privateOrJoin]="Join",[Prices]*40,IIf([UseCITSupVeDetail].[privateOrJoin]="SightVe",IIf(40 Mod [maxCapacity]=0,[Prices]*(40/[maxCapacity]),[Prices]*(Int(40/[maxCapacity])+1)),IIf(40>=[minCapacity] And 40<=[maxCapacity],IIf([fixedOrVar]="Fixed",[Prices],[Prices]*40),0)))
อธิบายโค๊ต
ถ้า สินค้า เป็นประเภท Join ให้นำราคาคูณ จำนวนคน แต่ถ้าเป็นประเภท SightVe (หมายถึง สินค้าประเภทการเดินทางเป็น join เช่น เรือ ซึ่งราคานับเป็นคันๆ) นำจำนวนคน หาร เพื่อให้ทราบจำนวนเรือที่ใช้ในการเดินทาง และถ้าหากเป็น Private (หลุด IIF) ก็ค้นดูว่า ราคานี้ ควรจะอยู่ตำแหน่งช่องนี้หรือไม่? โดยนำ จำนวนคน เทียบกับ จำนวนต่ำสุด และสูงสุด ของสินค้านี้ที่รองรับ เมื่อเป็น Private ก็ตรวจสอบอีกว่า สินค้านี้เป็นชนิด Fixed หรือ Variable เพื่อที่จะคำนวณราคาได้ถูกต้อง
ตัวอย่างโค๊ตที่แสดงราคานี้ มีจำนวน 7 ตารางๆ ละ 40 Column โดยประมาณ
หากนำมา UNION กัน จะต้องทำอย่างไรครับ ตอนนี้ที่ใช้อยู่คือ
Query1.* FROM Query1 UNION
Query2.* FROM Query2 UNION
.
.
.
Query7 * FROM Query7;
น่ะครับ และมีวิธีทางอื่นอีกไหม? ที่จะทำงานได้ดีกว่านี้ หรือเสถียรภาพกว่านี้
เพราะผมเขียนไปเรื่อยๆ ตอนนี้ มีความรู้สึกว่า Access เริ่มทำงานช้าลง เวลารันโค๊ตที่เกี่ยวกับ ตารางคำนวณพวกนี้
ขอบคุณล่วงหน้านะครับ
3 Reply in this Topic. Dispaly 1 pages and you are on page number 1
2 @R05849
เขียนเยอะแต่ไม่ละเอียดในสิ่งที่จำเป็นต่อคำถาม ก็ไม่แน่ใจว่าผมเข้าใจถูกหรือเปล่า เอาเป็นว่าผมแนะนำดังนี้
1) เข้าใจว่าแต่ละตารางแยกออกเพื่อเก็บทัวร์แต่ละประเภท ก็แนะนำว่า ไม่ต้องแยกเป็นหลายตาราง ปรับเปลี่ยนโดยเพิ่มอีกฟิลด์เข้าไปเพื่อบอกว่า เรคอร์ดนี้ๆเป็นของทัวร์ประเภทอะไรแทน แล้วก็เอาข้อมูลจากตารางรวมเป็นตารางเดียว ดังนั้นการใช้ Union ก็จะหมดไ? แต่เปลี่ยนเป็นกำหนดเงื่อนไขใน WHERE Clause เมื่อจะเลือกว่าจะเอาข้อมูลของทัวร์ประเภทอะไร
2) ช่อง 1 ถึง 40 เป็นช่องแสดงราคา ไม่ทราบว่าเป็นฟิลด์ในเทเบิลหรือไม่ หรือว่าเกิดจากการคำนวนตอนทำคิวรี่ ถ้าได้ เปลี่ยนให้เป็นฟิลด์ในเทเบิลเลยได้หรือไม่ แล้วคำนวนเก็บเอาไว้ก่อน จะได้ไม่เสียเวลามานั่งคำนวนทุกทีที่จะแสดงข้อมูล แต่ได้อย่างก็เสียอย่าง คือเมื่อฟิลด์ใดที่มีผลต่อราคาในช่อง 1 - 40 เปลี่ยนไป คุณก็ต้องมาสั่งให้เขาคำนวนใหม่ด้วยเช่นกัน
3) ถ้าข้อ 2) ยังทำตามที่แนะนำไม่ได้ และ การเลือกข้อมูลมานั้น ต้องมีการ join จากหลายๆเทเบิล แนะนำว่าอย่าเพิ่งคำนวนหาช่อง 1 ถึง 40 ไปพร้อมการ join ให้ทำการ join ให้เสร็จเป็น Query ตัวนึงเสียก่อน แล้วสร้าง Query ที่ 2 ที่อ้างผลจาก Query ที่1 แล้วจึงทำการคำนวนช่อง 1 - 40
1) เข้าใจว่าแต่ละตารางแยกออกเพื่อเก็บทัวร์แต่ละประเภท ก็แนะนำว่า ไม่ต้องแยกเป็นหลายตาราง ปรับเปลี่ยนโดยเพิ่มอีกฟิลด์เข้าไปเพื่อบอกว่า เรคอร์ดนี้ๆเป็นของทัวร์ประเภทอะไรแทน แล้วก็เอาข้อมูลจากตารางรวมเป็นตารางเดียว ดังนั้นการใช้ Union ก็จะหมดไ? แต่เปลี่ยนเป็นกำหนดเงื่อนไขใน WHERE Clause เมื่อจะเลือกว่าจะเอาข้อมูลของทัวร์ประเภทอะไร
2) ช่อง 1 ถึง 40 เป็นช่องแสดงราคา ไม่ทราบว่าเป็นฟิลด์ในเทเบิลหรือไม่ หรือว่าเกิดจากการคำนวนตอนทำคิวรี่ ถ้าได้ เปลี่ยนให้เป็นฟิลด์ในเทเบิลเลยได้หรือไม่ แล้วคำนวนเก็บเอาไว้ก่อน จะได้ไม่เสียเวลามานั่งคำนวนทุกทีที่จะแสดงข้อมูล แต่ได้อย่างก็เสียอย่าง คือเมื่อฟิลด์ใดที่มีผลต่อราคาในช่อง 1 - 40 เปลี่ยนไป คุณก็ต้องมาสั่งให้เขาคำนวนใหม่ด้วยเช่นกัน
3) ถ้าข้อ 2) ยังทำตามที่แนะนำไม่ได้ และ การเลือกข้อมูลมานั้น ต้องมีการ join จากหลายๆเทเบิล แนะนำว่าอย่าเพิ่งคำนวนหาช่อง 1 ถึง 40 ไปพร้อมการ join ให้ทำการ join ให้เสร็จเป็น Query ตัวนึงเสียก่อน แล้วสร้าง Query ที่ 2 ที่อ้างผลจาก Query ที่1 แล้วจึงทำการคำนวนช่อง 1 - 40
3 @R05930
ก่อนอื่นต้องขอโทษด้วยที่ให้ข้อมูลมากเกินไป จนคนอ่านแล้วหลงประเด็น
ครับ ขอบคุณ คุณ สันติสุข มากๆ นะครับ
จากคำแนะนำที่คุณให้คำแนะนำมา
1. ไม่สามารถทำได้ครับ เพราะข้อมูลสินค้าแต่ละตัวเก็บข้อมูลไม่เหมือนกัน ข้อมูลบางอย่าง มีเพียงแค่เฉพาะสินค้านั้นๆ สินค้าเดียว และมีปริมาณมาก (ยกตัวอย่างเช่น โรงแรม จะเก็บข้อมูลชื่อโรงแรม ชื่อชนิดห้อง ประเภทห้อง กลุ่มลูกค้า ฯลฯ และ ข้อมูลสายการบิน จะเก็บข้อมูล ชื่อสายการบิน เที่ยวบิน คลาสใหญ่ คลาสย่อย ฯลฯ ซึ่งจะเห็นได้ว่า ข้อมูลนั้นไม่เหมือนกันเลย แต่สุดท้าย จะได้ราคาออกมา สามารถนำมาคำนวณร่วมกันได้)
2. หากทำอย่างนั้น กรอกทีละช่องตั้งแต่ 1-40 สามารถทำได้ แต่.. จะเพิ่มภาระให้กับผู้ใช้งานน่ะครับ เพราะสินค้ามีปริมาณมาก (เห็นว่าเฉพาะสินค้าทั่วไป ไม่นับโรงแรม และสายการบิน มีจำนวน 3,000 กว่ารายการขึ้นไป และมีการอัพเดตตลอด)
3. วิธีนี้ช่วยผมได้มากเลยครับ ปัญหาที่พบคือ "Query is too complex" ผมทำตามที่ท่านแนะนำแล้ว ช่วยได้มากครับ คำนวณ แสดงผลได้ไวขึ้น แต่เกิดปัญหาอีกอย่างตามมาคือ "Cannot open any more databases." แทน
วิธีแก้ปัญหา "Cannot open any more databases." เบื้องต้นของผม
ผมตรวจสอบแล้วว่า ในฟอร์มของผมใน 1 หน้ามีการเรียกใช้ตารางขึ้นมามากมาย จึงได้ปรับปรุงเขียนโค๊ตใหม่ ออกแบบหน้าจอใหม่ ให้มีตารางน้อยลง (มี Subform น้อยลง โดยเน้น Subform ที่เกิดจากการคำนวณของ Query หรือ Query Join เป็นอย่างแรก) สิ่งไหนที่ไม่จำเป็นต้องเปิดหรือแสดงตลอด ก็ย้ายไปเป็นอีกฟอร์มหนึ่ง รอให้ผู้ใช้เรียกเปิดเอง และเปิดได้ทีละหน้าๆ เท่านั้น เพื่อป้องกันปัญหาเปิดตารางฐานข้อมูลมากเกินไป
ซึ่งก็ได้ผลครับ
ขอบคุณมากๆ ครับ
ครับ ขอบคุณ คุณ สันติสุข มากๆ นะครับ
จากคำแนะนำที่คุณให้คำแนะนำมา
1. ไม่สามารถทำได้ครับ เพราะข้อมูลสินค้าแต่ละตัวเก็บข้อมูลไม่เหมือนกัน ข้อมูลบางอย่าง มีเพียงแค่เฉพาะสินค้านั้นๆ สินค้าเดียว และมีปริมาณมาก (ยกตัวอย่างเช่น โรงแรม จะเก็บข้อมูลชื่อโรงแรม ชื่อชนิดห้อง ประเภทห้อง กลุ่มลูกค้า ฯลฯ และ ข้อมูลสายการบิน จะเก็บข้อมูล ชื่อสายการบิน เที่ยวบิน คลาสใหญ่ คลาสย่อย ฯลฯ ซึ่งจะเห็นได้ว่า ข้อมูลนั้นไม่เหมือนกันเลย แต่สุดท้าย จะได้ราคาออกมา สามารถนำมาคำนวณร่วมกันได้)
2. หากทำอย่างนั้น กรอกทีละช่องตั้งแต่ 1-40 สามารถทำได้ แต่.. จะเพิ่มภาระให้กับผู้ใช้งานน่ะครับ เพราะสินค้ามีปริมาณมาก (เห็นว่าเฉพาะสินค้าทั่วไป ไม่นับโรงแรม และสายการบิน มีจำนวน 3,000 กว่ารายการขึ้นไป และมีการอัพเดตตลอด)
3. วิธีนี้ช่วยผมได้มากเลยครับ ปัญหาที่พบคือ "Query is too complex" ผมทำตามที่ท่านแนะนำแล้ว ช่วยได้มากครับ คำนวณ แสดงผลได้ไวขึ้น แต่เกิดปัญหาอีกอย่างตามมาคือ "Cannot open any more databases." แทน
วิธีแก้ปัญหา "Cannot open any more databases." เบื้องต้นของผม
ผมตรวจสอบแล้วว่า ในฟอร์มของผมใน 1 หน้ามีการเรียกใช้ตารางขึ้นมามากมาย จึงได้ปรับปรุงเขียนโค๊ตใหม่ ออกแบบหน้าจอใหม่ ให้มีตารางน้อยลง (มี Subform น้อยลง โดยเน้น Subform ที่เกิดจากการคำนวณของ Query หรือ Query Join เป็นอย่างแรก) สิ่งไหนที่ไม่จำเป็นต้องเปิดหรือแสดงตลอด ก็ย้ายไปเป็นอีกฟอร์มหนึ่ง รอให้ผู้ใช้เรียกเปิดเอง และเปิดได้ทีละหน้าๆ เท่านั้น เพื่อป้องกันปัญหาเปิดตารางฐานข้อมูลมากเกินไป
ซึ่งก็ได้ผลครับ
ขอบคุณมากๆ ครับ
Time: 0.3255s
ขออนุญาติเข้ามาอ่าน แล้วขอเล่าประสบการ์ณของตัวเองสักหน่อย
...โดยปกติผมไม่ค่อยจะใช้ query union สักเท่าไรเพราะผมคิดว่ามันค่อนข้างช้า
ในกรณีที่ข้อมูลมากๆผมมักใช้ query append เพื่อให้ข้อมูลมันไปต่อกัน ผมมีความรู้สึกว่ามันไวกว่า... ยิ่งถ้ามีเงื่อนไขที่ซับซ้อนผมมักจะชอบฆ่าตัดตอน คือผมมักจะใช้ query make table ขึ้นมาสำหรับเงื่อนไขเบื้องต้น แล้วค่อยมาใส่เงื่อนไขซับซ้อนไปอีกที แม้จะเสียพื้นที่ไปบ้างแต่ผมว่ามันไม่งงดี
ขอโทษทีที่ผมไม่ได้อ่านข้อความของคุณโดยละเอียด ผมไม่รู้ว่าเรื่องเล่าของผมมันจะมีประโยชน์บ้างไหม ถ้าไม่ก็ถือว่าได้แลกเปลี่ยนละกัน รอท่านอื่นมาหาวิธีช่วย