若我有一個-庫存進出明細 (如附圖之上半部格式資料)
接下來用SQL取出最近出庫的明細
select * from 庫存進出 where 進出='出'
接下來該如何下SQL把其後帶出,每一筆出庫之對應(最近)前次的的進貨日如附圖(紅色處)
如果是 MSSQL 可以用如下指令:
<pre class="c" name="code">SELECT 品號, 進出, 數量, 日期, MAX(B.日期) AS 前次進貨日
FROM 庫存進出 AS A LEFT OUTER JOIN
庫存進出 AS B ON A.品號 = B.品號 AND A.日期 > B.日期
WHERE (B.進出 = 1) AND (A.進出 = - 1)
GROUP BY A.品號, A.進出, A.數量, A.日期
如果這樣 [湊] 就為了 [財務會計] 評價的問題
倒算出 [庫存] 是怎麼來的...
如果 [批量控管] 出貨單會有 [原進貨單號]
就不是這樣寫...
我們用 procedure 的 cursor loop
將 [進貨]
一個一個分配給 [出貨]
紀錄下 [出貨用了哪一個進貨]
[引][興]好像沒有模擬[耗用]
call me ,
Skype: Adempiere/Compiere
Albert
請不要回答出沒關係的答案.
由其拉出公司別,實在很不好.
我也不是在那家公司!!
本題目只是要求SQL語法
題目只是舉例,這樣比較好讓人寫出解答.
這真的是很糟糕的回答
請原諒我的直言.
你太聰明
連這個答案你也看不懂
無法配服你更多了
你的回答很棒
讚
hisniper提到:
請不要回答出沒關係的答案.
別在意
是你太久沒來這裡了
Albertachen大大的每一個答案
都是這麼讓人摸不著頭緒的
參考看看
<pre class="c" name="code">
--MSSQL
--建資料
Declare @tmp Table
(
[item] nvarchar(60),
[type] nvarchar(60),
[qty] numeric(9,0),
[date] date
)
INSERT INTO @tmp VALUES('A','IN',1,'2013/01/01')
INSERT INTO @tmp VALUES('A','OUT',-1,'2013/01/02')
INSERT INTO @tmp VALUES('A','IN',1,'2013/01/03')
INSERT INTO @tmp VALUES('A','OUT',-1,'2013/01/04')
INSERT INTO @tmp VALUES('B','IN',2,'2013/01/01')
INSERT INTO @tmp VALUES('B','OUT',-1,'2013/01/02')
INSERT INTO @tmp VALUES('B','OUT',-1,'2013/01/03')
INSERT INTO @tmp VALUES('C','IN',1,'2013/01/01')
INSERT INTO @tmp VALUES('C','IN',1,'2013/01/02')
INSERT INTO @tmp VALUES('C','OUT',-1,'2013/01/03')
INSERT INTO @tmp VALUES('C','IN',1,'2013/01/04')
;WITH Data_List AS(
SELECT a.*,b.date as out_date
FROM @tmp a
LEFT JOIN @tmp b on a.item =b.item and b.type = 'IN'
WHERE a.type = 'OUT'
AND DATEDIFF(D,a.date,b.date) < 0
)
SELECT item ,type ,qty ,date ,out_date
FROM (
SELECT MAX(out_date) OVER (PARTITION BY item ,date) AS SN,*
FROM Data_List
) tmp
WHERE SN = out_date
要的資料是本次的出貨記錄及前一次的出貨數量記錄..
建議使用標準SQL-92語法中的子查詢..
目的:1.可避免前一次無出貨的NULL請況,致本次資料無法輸出。
目的:2.不使用Join方式,以簡化程式的可看性。
程式飯粒:
SELECT item ,
type ,
qty ,
date ,
out_date ,
(Select Top 1 b.qty From FocusTableName b
Where b.item = a.item
And b.out_date < (Select MAX(c.out_date) From FocusTableName c
Where c.item = a.item)
Order By b.out_date Desc) AS Pre_qty
From FocusTableName
Where FocusTableName.type = 'OUT'
And FocusTableName.out_date = (Select MAX(D.out_date) From FocusTableName D
Where D.item = FocusTableName.item)
很有趣的問題, 如果資料不大的話可以把資料重新排序一下就可以了.
測試
準備
不怎麼好看的 SQL
如果只要出貨的部份, 那就讓第二次的 ecategory 不是 null 就好.
<pre class="c" name="code">
使用MySQL, 日期欄位修正為日期格式.
CREATE TABLE ithelp0326(
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
partno CHAR(1) NOT NULL,
tran CHAR(2) NOT NULL,
qty INT NOT NULL,
mdate DATE NOT NULL
);
INSERT INTO ithelp0326(partno, tran, qty, mdate) VALUES
('A', '進', 1, '2013-1-1'),
('A', '出', -1, '2013-1-2'),
('A', '進', 1, '2013-1-3'),
('A', '出', -1, '2013-1-4'),
('B', '進', 2, '2013-1-1'),
('B', '出', -1, '2013-1-2'),
('B', '出', -1, '2013-1-3'),
('C', '進', 1, '2013-1-1'),
('C', '進', 1, '2013-1-2'),
('C', '出', -1, '2013-1-3'),
('C', '進', 1, '2013-1-4');
SELECT a.partno, a.tran, a.qty, a.mdate, MAX(b.mdate) AS '前次進貨日'
FROM ithelp0326 a
LEFT JOIN ithelp0326 b
ON a.partno = b.partno
AND a.mdate > b.mdate
WHERE a.tran = '出'
AND b.tran = '進'
GROUP BY a.partno, a.mdate
ORDER BY a.partno, a.mdate;
結果如圖:
albertachen提到:
如果這樣寫只抓 :
同料號(partno)
出貨之前 a.mdate > b.mdate
最近一次 max(b.mdate)
如果只是語法的問題, hitomitanaka 的回答已經解決, 而且解得蠻漂亮的.
但是實務上, 我覺得這樣的資料結構應該會有很大的問題(效能).
比較洽當的方式應該是針對不同工廠, 品號之間的鋪貨table會去紀錄最近一次的進貨日期.
當你在撈取出貨明細時, 直接join 鋪貨的table即可馬上抓取最後一次進貨日.
避免資料庫過多的運算
這點在資料筆數很多時, 差異會很明顯.
用一點空間(多一個欄位)換取, 很划算的.
如果系統架構沒有鋪貨的table, 也可設計在即時庫存的table中
設計出好的架構需要許多經驗與切合實務上需求.
若是我的話,不會產生這種 "每一筆品項的出貨日期去查 最近進貨日期", 還一一列出來; 實務上品項會很多,即使是小公司少說也幾百,人類去一一看,也沒多大用處;
還不如去找出,最大差距,平均差距,或是每隔10天的數量累積等等; 再來就是依據供應廠商,產品大類,客戶等,再把剛剛的最大差距等等分別計算出來,會比單一項列出來,有意思多了.
模擬 [領用] 不是這樣寫
因為 [反核] 看到核桃就 [暈倒]
不是抓最後一筆
http://ithelp.ithome.com.tw/upload/images/20130327/2013032711032851526180e793f_thumb.jpg