2012-08-29 78 views
0

對不起,這個問題的通用名稱,但我不知道該怎麼把它..所以這裏有雲:這是可能的與SQL查詢?

我持有以下信息的單個表:

computerName | userName |   date   | logOn | startUp 
      |   |       |  | 
ID_000000001 | NULL | 2012-08-14 08:00:00.000 | NULL | 1 
ID_000000001 | NULL | 2012-08-15 09:00:00.000 | NULL | 0 
ID_000000003 | user02 | 2012-08-15 19:00:00.000 | 1 | NULL 
ID_000000004 | user02 | 2012-08-16 20:00:00.000 | 0 | NULL 

computername和用戶名是不言自明的我想

logOn1當用戶登錄在本機和0當他註銷時。

startUp1打開機器時和0關閉時。

其他條目分別是NULL,因爲我們無法在同一時間登錄和啓動。

現在我的任務是:找出哪些計算機已經開啓,在過去一個月中至少的時間(或任何給定時間量,但現在讓我們說一個月)這甚至與SQL可能? < - 小心:我並不需要知道一臺PC了多少次打開,但多少小時/分鐘,每次打開計算機在給定的時空

有兩個小問題,以及:

我們不能說每臺計算機的第一個條目是startUp列中的1,因爲記錄這些事件的腳本最近已安裝,因此計算機在開始記錄時已經運行。

我們不能假設,如果我們爲了通過date並只顯示startUp列條目都將交替的1和0,因爲如果計算機被強制拉動插頭例如關閉將不會有一個關機日誌,可能有兩個1連續。

編輯:userName當然是NULL,當startUp有一個值,因爲打開/關閉並沒有顯示哪個用戶這樣做。

+0

什麼樣的SQL? – podiluska

+0

MS SQL Server 2008對不起,忘了。 – Octoshape

+1

當你有強制關閉的情況下,因此在啓動欄中有兩個1,你想做什麼?你認爲它總是起來? – LaGrandMere

回答

1

在存儲過程中,使用遊標和提取循環。 而你使用一個臨時表來存儲計算機正常運行時間。 我給你主要計劃,我會讓你看看TSQL guide的細節。

另一個鏈接:a good example with TSQL Cursor

DECLARE @total_hour_by_computername  
declare @computer_name varchar(255) 
declare @RowNum int 

--Now in you ComputerNameList cursor, you have all different computernames: 
declare ComputerNameList cursor for 
select DISTINCT computername from myTable 

-- We open the cursor 
OPEN ComputerNameList 

    --You begin your foreach computername loop : 
    FETCH NEXT FROM ComputerNameList 
    INTO @computer_name 
    set @RowNum = 0 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 

    SET @total_hour_by_computername=0; 

    --This query selects all startup 1 dates by computername order by date. 
    select @current_date=date from myTable where startup = 1 and computername = @computername order by date 

     --You use a 2nd loop on the dates that were sent you back: 

     --This query gives you the previous date 
     select TOP(1) @previousDate=date from myTable 
     where computername = @computername and date < @current_date and startup is not null 
     order by date DESC 


     --If it comes null, you can decide not to take it into account. 
     --Else 
     SET @[email protected]_hour_by_computername+datediff(hour, @previousDate, @current_date); 

    --Once all dates have been parsed, you insert into your temptable the results for this computername 

    INSERT INTO TEMPTABLE(Computername,uptime) VALUES (@computername,@total_hour_by_computername) 

--End of the @computer_name loop 
    FETCH NEXT FROM ComputerNameList 
    INTO @computer_name 
END 
CLOSE ComputerNameList 
DEALLOCATE ComputerNameList 

你只需要一個選擇到你的臨時表中,以確定哪一臺計算機的時間最長。

+0

感謝你們,我如何使用SQL語法實現foreach循環?一個簡單的同時在表的ID? – Octoshape

+0

@Octoshape我編輯了我的答案,並給你第一個CURSOR循環。 – LaGrandMere

+0

@Octoshape你是否成功地執行了存儲過程? – LaGrandMere

1

,你可以按計算機,並用在哪裏爲創業過濾特定月份:

select computerName 
,  count(*) 
from YourTable 
where '2012-08-01' <= [date] and [date] < '2012-09-01' 
     and startup = 1 
group by 
     computerName 
order by 
     count(*) desc 
+0

我喜歡您的格式,爲您+1。 –

+0

對不起,我認爲這是非常ambigously寫道:我需要知道每臺計算機已打開的時間量,而不是次數< - 注意差異:)所以使用DATEDIFF或類似的東西 – Octoshape

0

嘗試此查詢(用您的表的名稱替換table_name):

SELECT SUM(startUp) AS startupTimes 
FROM table_name 
GROUP BY computerName 
ORDER BY startupTimes 

這將輸出每臺計算機啓動的次數。要獲得第一行(啓動次數最少的計算機),您可以在查詢中附加LIMIT 1

+0

對不起,我認爲這是非常ambigously寫:我需要知道每臺計算機已打開的時間量,而不是次數< - 注意差異:)所以使用DATEDIFF或類似的東西 – Octoshape

0

如果(根據您的最後一段)您沒有記錄所有關機事件。那麼您沒有可用的信息來生成顯示每臺計算機已啓動的時間的報告。由於您沒有記錄計算機關閉的所有實例,因此使用的SQL查詢無關緊要。

FWIW,這個模式不是3NF。更常見的做法是有一列記錄每一個事件,例如:

ComputerId:用戶名:事件ID:EVENTDATE

前三列各一個外鍵到另一個表,其中的細節都存儲。儘管即使使用這種模式,用戶ID對於啓動/關閉事件也是空的。

+0

你是對的,那麼我沒有做腳本:/我只接受任務來生成報表,並且是的,用戶ID對於啓動/關閉事件是空的,我將編輯 – Octoshape

+0

以及報告不會很準確,但我們已經決定簡單地考慮一臺計算機正在打開,直到下一次關機。所以我基本上只需要計算'startUp'列中的0到1之間的時間 – Octoshape

1

正如RoadWarrior指出的那樣,當關閉消息被丟棄時,不可能有準確的報告。但是這裏試圖產生一些有用的東西。我要去假設表名是computers

SELECT c1.computerName, 
     timediff(MIN(c2.date), c1.date) as upTime 
FROM computers as c1, computers as c2 
WHERE c1.computerName=c2.computerName 
    AND c1.startUp=1 AND c2.startUp=0 
    AND c2.date >= c1.date 
GROUP BY c1.date 
ORDER BY c1.date; 

,這將產生的所有周期的計算機是在列表。要生成您的請求報告,您可以使用上述查詢作爲子查詢:

SELECT 
    c3.computerName, 
    SEC_TO_TIME(SUM(TIME_TO_SEC(c3.upTime))) AS totalUpTime 
FROM 
    (SELECT c1.computerName, 
      timediff(MIN(c2.date), c1.date) AS upTime 
    FROM computers AS c1, computers AS c2 
    WHERE c1.computerName=c2.computerName 
    AND c1.startUp=1 AND c2.startUp=0 
    AND c2.date >= c1.date 
    GROUP BY c1.date 
    ORDER BY c1.date 
) AS c3 
GROUP BY c3.computerName 
ORDER BY c3.totalUpTime; 
+0

'c2.date> = c1.date'不夠強壯。如果電腦打開/關閉4次,你會得到4 * 3 * 2 * 1行。查詢必須在開啓後搜索第一個關閉,而不是全部搜索。 – Andomar

+0

但它。它將這些結果分組並將其中的最小值。 –

+0

我得到一個錯誤:''timediff'不是一個公認的內置函數名稱。「是否應該過時?但需要3個參數 – Octoshape