3

レコード内の値の間の変更の数を数えることが可能かどうか疑問に思いました

たとえば、私は次のデータを持っています

| radio | name | state | timestamp           |
|-------|------|-------|---------------------|
| 1     | AP1  | down  | 2013-03-07 10:00:00 |
| 1     | AP1  | down  | 2013-03-07 10:15:00 |
| 1     | AP1  | up    | 2013-03-07 10:30:00 |
| 1     | AP1  | down  | 2013-03-07 10:45:00 |
| 1     | AP1  | pend  | 2013-03-07 11:00:00 |
| 1     | AP1  | pend  | 2013-03-07 11:15:00 |
| 1     | AP1  | pend  | 2013-03-07 11:30:00 |
| 1     | AP1  | pend  | 2013-03-07 11:45:00 |

次のトリックを行うクエリを作成する必要があります

| name | S1     | S2     | S3       | S4         | (other time range) |
| AP1  | A      | A      | B        | A          | C                  |
                     \      /    \      /    \      /
                      DETECT      DETECT      DETECT    
                            \        \       / 
                             \------- \     /
                                       COUNT = 3 <-- this is the number i want

これまでのところ、カウントに基づくSQLで立ち往生しています。

SELECT radio, name, state, COUNT(state) AS count FROM data
WHERE timestamp BETWEEN '2013-03-07 10:00:00' AND '2013-03-07 11:00:00'
GROUP BY radio, name, channel

結果は次のようになります

| radio | name | state | count |
|-------|------|-------|-------|
| 1     | AP1  | down  | 3     |
| 1     | AP1  | up    | 1     |
| 1     | AP1  | pend  | 1     |

したがって、結果は3行、つまり3状態変化になりますが、この数は異なる状態名の数(この場合は3)しか教えてくれないため、これは正しくないことに気付きました。

だから私の質問は、これがSQLで可能かどうか、または結果セットをループにプルして、外部スクリプトまたはビューを介して変更を検出する必要があるかどうかです。

4

2 に答える 2

3

次のようなものを使用できます。

with Changes as
(
  select name
    , stateChange = case when prev.state is null then 0
      when sc.state <> prev.state then 1
      else 0
      end
  from data sc
    outer apply
    (
      select top 1 prev.state
      from data prev
      where sc.timestamp > prev.timestamp
        and sc.name = prev.name
      order by prev.timestamp desc
    ) prev
)
select name, stateChanges = sum(stateChange)
from Changes
group by name

demo を使用した SQL Fiddle

また、あなたの質問では、データに少し一貫性がありません。AP1について言及している場合もあれば、AP2について言及している場合もあります。上記のクエリ/フィドルでは不十分な場合は、より大きなデータセットを提供してください。

于 2013-03-08T10:08:06.210 に答える
2

LAG()を使用できます:

SELECT sq.RADIO,
  sq.NAME,
  COUNT(CASE WHEN sq.STATE != sq.PREV_STATE THEN 1 ELSE NULL END) CHG_COUNT
FROM
  (SELECT 
    td.RADIO,
    td.NAME,
    td.STATE,
    COALESCE(LAG(td.STATE,1) OVER(PARTITION BY td.RADIO, td.NAME ORDER BY td.TIMESTAMP ASC),td.STATE) PREV_STATE
  FROM DATA td) sq
GROUP BY sq.RADIO, 
  sq.NAME
于 2013-03-08T10:35:45.153 に答える