2013-04-04 19 views
3

我想製作一個SQL語句來從數據庫中提取樣本值。該表格包含與CNC機牀中刀具更換有關的值。當前的語句我已經正確地提取了值,但是隻有當某個給定程序中有一個該工具發生時。如果該工具出現多次,則時間值對應於第一次加載到最後一次加載。只有一個TIME列,通過查找它的第一次和最後一次出現,我可以確定一個工具進/出時間。SQL查詢按時間對項目進行分組,但僅在彼此靠近時才分組?

基本例如:

Raw Data: 
Tool_Number TIME  
100   12:00 
100   12:01 
100   12:02 
100   12:03 

Current Query Returns: 
Tool_Number TIME_IN  TIME_OUT  
100   12:00  12:03 

事情會很麻煩當工具出現多次,雖然,因爲我不能再利用TOP和DISTINCT規則。

Raw Data: 
Tool_Number TIME  
100   12:00 
100   12:01 
100   12:02 
100   12:03 
200   12:04 
200   12:05 
100   12:06 
100   12:07 

Current Query Returns: 
Tool_Number TIME_IN  TIME_OUT  
100   12:00  12:07 
200   12:04  12:05 

Ideal Query Returns: 
Tool_Number TIME_IN  TIME_OUT  
100   12:00  12:03 
200   12:04  12:05 
100   12:06  12:07 

我們正在做時間分析,當然這嚴重地搞亂了總的時間值。 當前查詢:

SELECT * FROM (SELECT DISTINCT SPINDLE_POT FROM TBL_SPINDLE_DATA_M1 
WHERE TIME BETWEEN '4/3/20131:24:13 PM' AND '4/3/2013 3:07:33 PM') AS A 

CROSS APPLY 

((SELECT TOP 1 TIME FROM TBL_SPINDLE_DATA_M1 B WHERE B.SPINDLE_POT = A.SPINDLE_POT AND 
TIME BETWEEN '4/3/2013 1:24:13 PM' AND '4/3/2013 3:07:33 PM') AS NEWTABLE1 

JOIN 

(SELECT TOP 1 TIME FROM TBL_SPINDLE_DATA_M1 B WHERE B.SPINDLE_POT = A.SPINDLE_POT 
AND TIME BETWEEN '4/3/2013 1:24:13 PM' AND '4/3/2013 3:07:33 PM' ORDER BY TIME DESC) 
AS NEWTABLE2 ON (0=0)) 

我絕不是任何種類的SQL查詢專家!上面的查詢可能是非常錯誤的,但事實上它返回了我需要的東西。無論如何都要將類似的項目分組,但是如果他們的指標不相互接觸,那麼他們是否足夠司法,不能將他們分組?

+1

我假設SQL Server由於使用了'APPLY',但你應該確保你標記你的問題與適當的數據庫。 – Taryn 2013-04-04 18:11:52

+0

謝謝,我也在使用SQL 2012。代碼已更新。 – 2013-04-04 18:13:46

+1

值是什麼標準被視爲兩個單獨的「批」而不是一個?兩者之間是否必須沒有時間差距,即只要條目以連續方式出現(分鐘),條目就被視爲一個批次?還是說它們之間不能有任何其他工具條目(按時間順序)? – 2013-04-04 18:19:42

回答

7

下面是使用LAG/LEAD另一種方法:

DECLARE @rawdata TABLE(Tool_Number INT, [Time] TIME(0)); 

INSERT @rawdata VALUES 
(100,'12:00'), (100,'12:01'), (100,'12:02'), (100,'12:03'), 
(200,'12:04'), (200,'12:05'), 
(100,'12:06'), (100,'12:07'); 

;WITH x AS 
(
    SELECT Tool_Number, [Time], 
    s = CASE Tool_number WHEN LAG(Tool_number,1) OVER (ORDER BY [Time]) 
     THEN 0 ELSE 1 END, 
    e = CASE Tool_number WHEN LEAD(Tool_number,1) OVER (ORDER BY [Time]) 
     THEN 0 ELSE 1 END 
    FROM @rawdata 
), 
y AS 
(
    SELECT Tool_Number, s, [Time], e = LEAD([Time],1) OVER (ORDER BY [Time]) 
    FROM x WHERE 1 IN (s,e) 
) 
SELECT Tool_number, TIME_IN = [Time], TIME_OUT = e 
FROM y 
WHERE s = 1 
ORDER BY TIME_IN; 

結果:

Tool_number TIME_IN TIME_OUT 
----------- -------- -------- 
100   12:00:00 12:03:00 
200   12:04:00 12:05:00 
100   12:06:00 12:07:00 
+0

這個工作很好,比我拼湊在一起的當前'破壞'實現快得多。萬分感謝! – 2013-04-04 19:40:09

+0

不錯。太糟糕了[當一個小島由單一行組成時不能正常工作](http://sqlfiddle.com/#!6/86bc2/1)。 – 2013-04-04 20:31:06

+0

不知道是否有很多方法可以解決這個問題,但是將'y'中的'e'表達式改爲'e = CASE e當時1 [時間] ELSE LEAD([Time],1)OVER(ORDER BY [Time])END' [似乎工作](http://sqlfiddle.com/#!6/86bc2/2)。 – 2013-04-04 20:41:10

9

這就是所謂的「孤島問題」,我已經看到了這個作爲一個解決方案(信用伊茨克奔甘)

select tool_number, 
     min(time) 'in', 
     max(time) 'out', 
     count(*) 
from (
    select tool_number, 
      time, 
      ROW_NUMBER() OVER (ORDER BY time) - ROW_NUMBER() OVER (PARTITION BY Tool_Number ORDER BY time) AS Grp 
    from #temp 
    ) as a 
group by grp, tool_number 
order by min(time) 
+3

+1,喜歡'Grp'計算。 – 2013-04-04 18:34:41

+0

不錯的解決方案,作爲獎勵將在2005+工作。我只是添加了LAG/LEAD解決方案,因爲我可以(2012年的問題非常少見),並且因爲它似乎會導致更好的計劃(我的解決方案只有一種,而您的解決方案只有三種)。 – 2013-04-04 19:06:28