หาค่า 3 ลำดับสุดท้าย
กระทู้เก่าบอร์ด อ.Yeadram

 1,605   18
URL.หัวข้อ / URL
หาค่า 3 ลำดับสุดท้าย

มี table : visit
มี ฟิลด์
seq : ลำดับรับบริการ
visitdate : วันที่มารับบริการ
pid : รหัสลูกค้า
tot : มูลค่าซื้อ

จะเขียน Query ให้มูลค่าซื้อของลูกค้า เรียงลำดับ 3 ครั้งสุดท้าย
ต้องเขียนแบบไหนครับ

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

1 @R23013
select tot from visit where pid='xxx'   order by visitdate desc limit 3

ประมาณนี้มั้งครับ เดาๆเอา
แต่คำสั่ง limit มันใช้ได้ไหม ใน access ผมไม่แน่ใจ
ไม่เคยลอง
2 @R23015
แบบนี้ผมทำได้ครับ คือแบบอยากให้ไม่ต้องกำหนด WHERE เป็นคนๆ ครับ
อยากให้ออกมาทุกคนเลย เรียงลำดับ 3 อันดับแรก ขอบคุณครับ
3 @R23020
ในเว็บส่วนมากเค้าชอบทำกันแบบนี้ครับ

SELECT Top 3 * FROM visit ORDER BY seq DESC

ลองดูว่าตรงตามข้อมูลที่ต้องการหรือไม่ครับ
4 @R23025
แบบนี้จะออกมา 3 รายการ ซึ่งแบบที่ต้องการคือ

visitdate       pid       tot
5/3/2560        1        30
1/1/2560        1        20
7/1/2560        3       400
5/12/2559      3        20
8/5/2559        3       100
6/12/2559      4        10
7/11/2559       4       400
5/9/2559        4        20

pid 1 มาแค่ 2 ครั้ง นอกนั้นมา 3 ครั้งขึ้นไป เอาแค่ 3 ประมาณนี้ครับ
5 @R23029
อื่ม... หากหมายถึงต้องการคิวรี่แสดงฐานข้อมูลล่าสุด 3 รายการสุดท้ายของทุกๆ Pid อย่างนั้นหรือเปล่า (ไม่เคยเข้าใจนะ) หากใช่ เท่าที่คิดออกตอนนี้ คือ...

น่าจะต้องคิวรี่ 3 ครั้ง แล้วนำมา Union all กันมั้งครับ คือ
1. คิวรี่ข้อมูลรายการครั้งสุดท้ายของทุก pid
2. คิวรี่ข้อมูลรายการรองครั้งสุดท้ายของทุก pid
3. คิวรี่ข้อมูลรายการของก่อนรองครั้งสุดท้ายของทุก pid
แล้วนำ 3 คิวรี่นี้มา Union all กัน อะไรประมาณนี้ครับ

จากตัวอย่างก็จะได้ประมาณนี้ครับ

SELECT *
FROM (SELECT DISTINCT
(SELECT Last(seq) FROM visit AS b WHERE b.pid = a.pid) AS seq,
(SELECT Last(pid) FROM visit AS b WHERE b.pid = a.pid) AS pid,
(SELECT Last(visitdate) FROM visit AS b WHERE b.pid = a.pid) AS visitdate,
(SELECT Last(tot) FROM visit AS b WHERE b.pid = a.pid) AS tot
FROM visit AS a
GROUP BY a.pid, a.seq

UNION ALL

SELECT DISTINCT
(SELECT Last(seq) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS seq,
(SELECT Last(pid) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS pid,
(SELECT Last(visitdate) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS visitdate,
(SELECT Last(tot) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS tot
FROM (SELECT DISTINCT
(SELECT Last(seq) FROM visit AS b WHERE b.pid = a.pid) AS seq,
(SELECT Last(pid) FROM visit AS b WHERE b.pid = a.pid) AS pid
FROM visit AS a
GROUP BY a.pid, a.seq) AS a
GROUP BY a.pid, a.seq
HAVING Not (SELECT Last(seq) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) Is Null

UNION ALL

SELECT DISTINCT
(SELECT Last(seq) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS seq,
(SELECT Last(pid) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS pid,
(SELECT Last(visitdate) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS visitdate,
(SELECT Last(tot) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS tot
FROM (SELECT DISTINCT
(SELECT Last(seq) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS seq,
(SELECT Last(pid) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) AS pid
FROM (SELECT DISTINCT
(SELECT Last(seq) FROM visit AS b WHERE b.pid = a.pid) AS seq,
(SELECT Last(pid) FROM visit AS b WHERE b.pid = a.pid) AS pid
FROM visit AS a
GROUP BY a.pid, a.seq) AS a
GROUP BY a.pid, a.seq) AS a
GROUP BY a.pid, a.seq
HAVING Not (SELECT Last(seq) FROM visit AS b WHERE b.pid = a.pid AND b.seq < a.seq) Is Null) AS LAS
ORDER BY LAS.pid;

ปล. ไม่รู้ว่าเป็นแนวคิดดีสุดยังนะครับ นึกๆดูยังนึกออกได้เท่านี้ โจทย์แบบนี้ไม่เคยเจอ แต่เป็นโจทย์น่าสนใจดีครับ อาจมีแนวคิดดีกว่านี้จากอาจารย์ท่านอื่นๆ ก็ได้ครับ ลองปรับใช้ดูก่อน
6 @R23039
มันประมวลผลประมาณ 10 นาทีแล้วครับ ยังไม่หยุด
7 @R23041
โค๊ดข้างบนผมคิดได้ก็เขียนเลย ดูแล้วเหมือนมันมีการใช้คำสั่งซ้ำ ใช้ Distinct แล้วยังใช้ Group by อีก และมีบางอย่างก็ลดคำสั่งลงได้ น่าจะทำให้เร็วขึ้นได้ แต่ดูแล้วก็ยังไม่ค่อยฉลาดเท่าไหร่หากนำไปใช้กับข้อมูลเรคคอร์ดเยอะ ยังไงลองทดสอบดูใหม่ครับ

SELECT *
FROM (SELECT DISTINCT a.Pid,
(SELECT Last(seq) FROM visit AS b WHERE b.Pid = a.Pid) AS seq,
(SELECT Last(visitdate) FROM visit AS b WHERE b.Pid = a.Pid) AS visitdate,
(SELECT Last(tot) FROM visit AS b WHERE b.Pid = a.Pid) AS tot
FROM visit AS a

UNION ALL

SELECT DISTINCT a.Pid,
(SELECT Last(seq) FROM visit AS b WHERE b.Pid = a.Pid AND b.seq < a.seq) AS seq,
(SELECT Last(visitdate) FROM visit AS b WHERE b.Pid = a.Pid AND b.seq < a.seq) AS visitdate,
(SELECT Last(tot) FROM visit AS b WHERE b.Pid = a.Pid AND b.seq < a.seq) AS tot
FROM (SELECT DISTINCT a.Pid,
(SELECT Last(seq) FROM visit AS b WHERE b.Pid = a.Pid) AS seq
FROM visit AS a) AS a
WHERE Not (SELECT Last(seq) FROM visit AS b WHERE b.Pid = a.Pid AND b.seq < a.seq) Is Null

UNION ALL

SELECT DISTINCT a.Pid,
(SELECT Last(seq) FROM visit AS b WHERE b.Pid = a.Pid AND b.seq < a.seq) AS seq,
(SELECT Last(visitdate) FROM visit AS b WHERE b.Pid = a.Pid AND b.seq < a.seq) AS visitdate,
(SELECT Last(tot) FROM visit AS b WHERE b.Pid = a.Pid AND b.seq < a.seq) AS tot
FROM (SELECT DISTINCT a.Pid,
(SELECT Last(seq) FROM visit AS b WHERE b.Pid = a.Pid AND b.seq < a.seq) AS seq
FROM (SELECT DISTINCT a.Pid,
(SELECT Last(seq) FROM visit AS b WHERE b.Pid = a.Pid) AS seq
FROM visit AS a) AS a) AS a
WHERE Not (SELECT Last(seq) FROM visit AS b WHERE b.Pid = a.Pid AND b.seq < a.seq) Is Null) AS qry_Last3
ORDER BY qry_Last3.Pid, qry_Last3.seq;
8 @R23045
ลองดูว่าอย่างนี้ได้ไหม (ผมยังไม่ได้ทดสอบนะ)

select v1.visitdate, v1.pid, v1.tot from visit as v1
where v1.visitdate in (select top 3 v2.visitdate from visit as v2
                               where v2.pid = v1.pid
                               order by v2.visitdate desc)
order by   v1.pid, v1.visitdate desc
9 @R23046
แหม ๆ ท่าน อ.สันติฯ เขียนสั้นยังงี้นักเรียนคงเข้าใจง่ายเนอะ
10 @R23047
แล้วที่คุณ UN บอกว่าประมวลผล 10 นาทียังไม่หยุดน่ะ ข้อมูลมากหรือเครื่องช้ากันแน่ บอกเดี๊ยนที
11 @R23048
อย่างที่ว่าไว้ ผมยังไม่ได้รันทดสอบครับ (แต่ syntax ไม่ผิดแน่ๆ) อาจทำงานไม่ตรงตามที่ต้องการหรือทำงานผิดก็ได้นะครับ คุณ UN ไปทดสอบเองแล้วกัน
12 @R23049
ผมทดสอบ SQL ของ อ.สันติสุข แล้วครับ
คิดว่าน่าจะถูกต้อง ตรงตามที่ผมเข้าใจแล้ว

รอคุณ Un มายืนยันคำตอบครับ
13 @R23057
เยี่ยมเลยครับ
14 @R23080
ขอโทษอาจารย์ทุกท่านครับ ผมทดสอบของ อ.TTT ยังไม่เสร็จเลยครับ มัน Err กำลังหาจุดอยู่ แล้วงานอื่นๆ มันยุ่งมาก เพิ่งเข้ามาอ่านอีกทีตอนนี้

ตอบ อ.U&ME เครื่องผมเครื่องใหม่ Corei5 DDR 4 GB น่าจะเร็ว
ส่วนข้อมูล จริงๆ ก็มากอยู่ 2-3 หมื่นเรคคอด แต่ผมใช้ คิวรี กรอง เหลือ 5000 เรคคอด


ตอบ อ.PichaiTC ตอนนี้ สิบกว่านาที ยังรันอยู่ครับ (ของ อ.สันติสุข) กำลังทำความเข้าใจกับสูตรอยู่ครับ

ขอบพระคุณอาจารย์ทุกท่านครับ
15 @R23081
ถ้าช้า ให้สร้าง index อีกตัวนึง ที่ประกอบด้วย pid และ visitdate ครับ
16 @R23082
หมายถึง ให้ไปกำหนดที่ตารางใช่มั้ยครับ หรือทำในควิรีครับอาจารย์
17 @R23084
กำหนดในตารางครับ คิวรี่ไม่มีการสร้าง index ครับ
18 @R23085
ทำแล้ว สรุป ไม่เวิคครับ สงสัยต้องใช้วิธีอื่นครับอาจารย์
@ ประกาศใช้งานเว็บบอร์ดใหม่ => บอร์ดเรียนรู้ Access สำหรับคนไทย
แล้วจะใส่ลิ้งอ้างอิงมาที่โพสต์เก่านี้หรือไม่ก็ตามสะดวกครับ
Time: 0.3449s