6

以下のコードは、特定の日数をさかのぼる期間 (期間は YYYY,WW) の解決されたチケットの数とオープンされたチケットの数を返します。たとえば、@NoOfDays が 7 の場合:

解決 | 開いた | 週 | 年 | 限目

56 | 30 | 13 | 2012年 | 2012年13月

237 | 222 | 14 | 2012年 | 2012年14月

「解決済み」と「開封済み」は、期間 (x) にわたって線 (y) でグラフ化されます。期間にわたってグラフ化されたときに傾向線 (単純な線形回帰) になる数値を返す別の列「傾向」を追加したいと思います。傾向の 1 つのデータ ソースとして両方の値のセットを使用たいと考えています。

これは私が持っているコードです:

SELECT a.resolved, b.opened, a.weekClosed AS week, a.yearClosed AS year,
    CAST(a.yearClosed as varchar(5)) + ', ' + CAST(a.weekClosed as varchar(5)) AS period
FROM 
    (SELECT TOP (100) PERCENT COUNT(DISTINCT TicketNbr) AS resolved, { fn WEEK(date_closed) } AS weekClosed, { fn YEAR(date_closed) } AS yearClosed
    FROM v_rpt_Service
    WHERE (date_closed >= DateAdd(Day, DateDiff(Day, 0, GetDate()) - @NoOfDays, 0))
    GROUP BY { fn WEEK(date_closed) }, { fn YEAR(date_closed) }) AS a 
LEFT OUTER JOIN
    (SELECT TOP (100) PERCENT COUNT(DISTINCT TicketNbr) AS opened, { fn WEEK(date_entered) } AS weekEntered, { fn YEAR(date_entered) 
    } AS yearEntered
    FROM v_rpt_Service AS v_rpt_Service_1
    WHERE        (date_entered > = DateAdd(Day, DateDiff(Day, 0, GetDate()) - @NoOfDays, 0))
    GROUP BY { fn WEEK(date_entered) }, { fn YEAR(date_entered) }) AS b ON a.weekClosed = b.weekEntered AND a.yearClosed = b.yearEntered
ORDER BY year, week

編集:

serc.carleton.edu/files/mathyouneed/best_fit_line_dividing.pdf によると、データを半分に分割してから平均を計算したいようです。次に、最適な線を見つけ、勾配と y 切片を使用して、y = mx + b?

これが SQL で非常に可能であることはわかっていますが、SQL を挿入するプログラムには、実行できることが制限されています。

赤と青のドットは、私が現在返している数字です(開いて解決しました)。紫色の線を作成するには、「トレンド」のすべての期間の値を返す必要があります。(この画像は架空のものです)

仮想チャート

4

3 に答える 3

5

私はこの問題に興味があり、複雑なクエリを理解する最善の方法は、独自のスタイルと規則を使用して再フォーマットすることであることがわかりました。それらをあなたのソリューションに適用しました。結果は以下のとおりです。これがあなたにとって価値があるかどうかはわかりません...

  • ({fn xxx }andWEEK(xxx)関数など、MS T-SQL 構文の一部とは思えないコードがいくつかありました。
  • このコードはコンパイルされますが、データ テーブルが適切に構成されていないため実行できません。
  • 私は多くのコーディングの変更を行いましたが、それらはかなり多くの説明を要しますが、そのほとんどは省略します。説明が必要な場合は、コメントを追加してください。
  • 余白をたくさん入れました。判読できるコードと判読できないコードの違いは、多くの場合、見る人の認識と感性にすぎないため、私の慣習を嫌うかもしれません。
  • 最終的な結果セットがどうあるべきかわからない (つまり、どの列が返されるか)

さらにいくつかの注意事項:

  • このクエリは、その週にアイテムがクローズされていない場合、その週に入力されたアイテムを取得しません
  • 週は部分的である場合があります。たとえば、7 日すべてが存在するわけではありません (@Interval を調整して、常に完全な週を含めるようにします -- しかし、奇数の間隔はどうでしょうか?)
  • count(*) 値に 1.0 を掛けて、早い段階で float に変換します (キャストと整数演算の切り捨てを回避します)。
  • 以前の数式を後の数式の記号に置き換えることができるように cte を作成しました (その時点で、物事はより読みやすくなりました)

だからここに私が思いついたものがあります:

;WITH cte as (
select
   c.period
  ,resolved_half1
  ,resolved_half2
  ,opened_half1
  ,opened_half2
  ,row = row_number() over(order by c.yearClosed, c.weekClosed)
  ,y1 = ((SUM(resolved_half1) + SUM(opened_half1)) - (SUM(resolved_half2) + SUM(opened_half2))) / ((count(resolved_half1) + count(opened_half1)) / 2)
  ,y2 = ((SUM(resolved_half2) + SUM(opened_half2)) / (count(resolved_half2) + COUNT (opened_half2)))
  ,x1 = ((count(c.period)) / 4)
  ,x2 = (((count(c.period)) / 4) * 3)
 from (select
          a.yearclosed
         ,a.weekClosed
         ,a.resolved_half1
         ,b.yearEntered
         ,b.weekEntered
         ,b.opened_half1
         ,cast(a.yearClosed as varchar(5)) + ', ' + cast(a.weekClosed as varchar(5))  period 
        from (--  Number of items per week that closed within @Interval
              select
                 count(distinct TicketNbr) * 1.0  resolved_half1
                ,datepart(wk, date_closed)        weekClosed
                ,year(date_closed)                yearClosed
               from v_rpt_Service 
               where date_closed >= @FullInterval
               group by
                 datepart(wk, date_closed)
                ,year(date_closed) )  a
         left outer join (--  Number of items per week that were entered within @Interval
                          select 
                             count(distinct TicketNbr) * 1.0  opened_half1
                            ,datepart(wk, date_entered)       weekEntered
                            ,year(date_entered)               yearEntered
                           from v_rpt_Service
                           where date_entered >= @FullInterval
                           group by
                             datepart(wk, date_entered)
                            ,year(date_entered) )  b
          on a.weekClosed = b.weekEntered 
           and a.yearClosed = b.yearEntered)  c
  left outer join (select
                       d.yearclosed
                      ,d.weekClosed
                      ,d.resolved_half2
                      ,e.yearEntered
                      ,e.weekEntered
                      ,e.opened_half2
                      ,cast(yearClosed as varchar(5)) + ', ' + cast(weekClosed as varchar(5))  period 
                    from (select
                             count(distinct TicketNbr) * 1.0  resolved_half2
                            ,datepart(wk, date_closed)        weekClosed
                            ,year(date_closed)                yearClosed
                           from v_rpt_Service
                           where date_closed >= @HalfInterval
                           group by
                             datepart(wk, date_closed) 
                            ,year(date_closed) )  d 
                     left outer join (select
                                         count(distinct TicketNbr) * 1.0  opened_half2
                                        ,datepart(wk, date_entered)       weekEntered
                                        ,year(date_entered)               yearEntered
                                       from v_rpt_Service
                                       where date_entered >= @HalfInterval
                                       group by
                                           datepart(wk, date_entered) 
                                          ,year(date_entered) )  e
                      on d.weekClosed = e.weekEntered
                       and d.yearClosed = e.yearEntered )  f
   on c.period = f.period 
 group by
   c.period
  ,resolved_half1
  ,resolved_half2
  ,opened_half1
  ,opened_half2
  ,c.yearClosed
  ,c.weekClosed
)
SELECT
   row
  ,Period
  ,x1
  ,y1
  ,x2
  ,y2
  ,m = ((y1 - y2) / (x1 - x2))
  ,b = (y2 - (((y1 - y2) / (x1 - x2)) * x2))
  ,trend = ((((y1 - y2) / (x1 - x2)) * (row)) + (y2 - (((y1 - y2) / (x1 - x2)) * x2)))
 from cte
 order by row 

補足として、サブクエリ「c」のすべてを次のようなものに置き換え、「f」をわずかに変更したバージョンに置き換えることができます。パフォーマンスの良し悪しは、テーブルのサイズ、インデックス作成、およびその他の計り知れない要素によって異なります。

select
   datepart(wk, date_closed)  weekClosed
  ,year(date_closed)          yearClosed
  ,count (distinct case
                  when date_closed >= @FullInterval then TicketNbr
                  else null
                end)          resolved_half1
  ,count (distinct case
                  when date_entered >= @FullInterval then TicketNbr
                  else null
                end)          opened_half1
 from v_rpt_Service 
 where date_closed >= @FullInterval
  or date_entered >= @FullInterval
 group by
   datepart(wk, date_closed)
  ,year(date_closed) 
于 2012-04-12T18:41:07.047 に答える
1

私はそれを考え出した。データを複数の派生テーブルとサブクエリに分割し、実質的にデータを半分に分割しました。これらは、各値を取得するための私の式です:

*(each row is a week)*
y1 = average of data first half
y2 = average of data second half
x1 = 1/4 of number of weeks
x2 = 3/4 of number of weeks
m = (y1-y2)/(x1-x2)
b = y2 - (m * x2)
trend = (m * row_number) + b 

そして、これが私の(非常に汚い)SQLコードです:

SELECT  resolved_half1,resolved_half2,opened_half1,opened_half2, c.period,
((SUM (resolved_half1) OVER () + SUM(opened_half1) OVER ()) - (SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ())) / ((COUNT(resolved_half1) OVER () + COUNT(opened_half1) OVER ()) / 2) as y1, 
((SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ()) / (COUNT(resolved_half2) OVER () + COUNT (opened_half2) OVER ())) as y2,
((COUNT(c.period) OVER ()) / 4) as x1,
(((COUNT(c.period) OVER ()) / 4) * 3) as x2,
((CAST(((SUM (resolved_half1) OVER () + SUM(opened_half1) OVER ()) - (SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ())) / ((COUNT(resolved_half1) OVER () + COUNT(opened_half1) OVER ()) / 2) as float) - CAST(((SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ()) / (COUNT(resolved_half2) OVER () + COUNT (opened_half2) OVER ())) as float)) / (CAST(((COUNT(c.period) OVER ()) / 4) as float) - CAST( (((COUNT(c.period) OVER ()) / 4) * 3) as float))) as m,
(CAST(((SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ()) / (COUNT(resolved_half2) OVER () + COUNT (opened_half2) OVER ())) as float) - (((CAST(((SUM (resolved_half1) OVER () + SUM(opened_half1) OVER ()) - (SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ())) / ((COUNT(resolved_half1) OVER () + COUNT(opened_half1) OVER ()) / 2) as float) - CAST(((SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ()) / (COUNT(resolved_half2) OVER () + COUNT (opened_half2) OVER ())) as float)) / (CAST(((COUNT(c.period) OVER ()) / 4) as float) - CAST( (((COUNT(c.period) OVER ()) / 4) * 3) as float))) * (((COUNT(c.period) OVER ()) / 4) * 3))) as b,
((((CAST(((SUM (resolved_half1) OVER () + SUM(opened_half1) OVER ()) - (SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ())) / ((COUNT(resolved_half1) OVER () + COUNT(opened_half1) OVER ()) / 2) as float) - CAST(((SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ()) / (COUNT(resolved_half2) OVER () + COUNT (opened_half2) OVER ())) as float)) / (CAST(((COUNT(c.period) OVER ()) / 4) as float) - CAST( (((COUNT(c.period) OVER ()) / 4) * 3) as float))) * (ROW_NUMBER() OVER(ORDER BY c.yearClosed,c.weekClosed))) + (CAST(((SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ()) / (COUNT(resolved_half2) OVER () + COUNT (opened_half2) OVER ())) as float) - (((CAST(((SUM (resolved_half1) OVER () + SUM(opened_half1) OVER ()) - (SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ())) / ((COUNT(resolved_half1) OVER () + COUNT(opened_half1) OVER ()) / 2) as float) - CAST(((SUM(resolved_half2) OVER () + SUM(opened_half2) OVER ()) / (COUNT(resolved_half2) OVER () + COUNT (opened_half2) OVER ())) as float)) / (CAST(((COUNT(c.period) OVER ()) / 4) as float) - CAST( (((COUNT(c.period) OVER ()) / 4) * 3) as float))) * (((COUNT(c.period) OVER ()) / 4) * 3)))) as trend,
ROW_NUMBER() OVER(ORDER BY c.yearClosed,c.weekClosed) as row

FROM
    (SELECT *, CAST(yearClosed as varchar(5)) + ', ' + CAST(weekClosed as varchar(5)) AS period
     FROM  (SELECT        TOP (100) PERCENT COUNT(DISTINCT TicketNbr) AS resolved_half1, { fn WEEK(date_closed) } AS weekClosed, { fn YEAR(date_closed) } AS yearClosed
                          FROM            v_rpt_Service
      WHERE (date_closed >= DateAdd(Day, DateDiff(Day, 0, GetDate()) - (180), 0))

      GROUP BY { fn WEEK(date_closed) }, { fn YEAR(date_closed) }) AS a 
      LEFT OUTER JOIN
      (SELECT TOP (100) PERCENT COUNT(DISTINCT TicketNbr) AS opened_half1, { fn WEEK(date_entered) } AS weekEntered, { fn YEAR(date_entered) 
       FROM v_rpt_Service AS v_rpt_Service_1
       WHERE (date_entered > = DateAdd(Day, DateDiff(Day, 0, GetDate()) - (180), 0))
       GROUP BY { fn WEEK(date_entered) }, { fn YEAR(date_entered) }) AS b ON a.weekClosed = b.weekEntered AND a.yearClosed = b.yearEntered) as c 
       LEFT OUTER JOIN
       (SELECT *, CAST(yearClosed as varchar(5)) + ', ' + CAST(weekClosed as varchar(5)) AS period 
       FROM  (SELECT TOP (100) PERCENT COUNT(DISTINCT TicketNbr) AS resolved_half2, { fn WEEK(date_closed) } AS weekClosed, { fn YEAR(date_closed) } AS yearClosed
       FROM v_rpt_Service
       WHERE (date_closed >= DateAdd(Day, DateDiff(Day, 0, GetDate()) - (180 / 2), 0))
       GROUP BY { fn WEEK(date_closed) }, { fn YEAR(date_closed) }) AS d 
       LEFT OUTER JOIN
       (SELECT TOP (100) PERCENT COUNT(DISTINCT TicketNbr) AS opened_half2, { fn WEEK(date_entered) } AS weekEntered, { fn YEAR(date_entered)} AS yearEntered
       FROM v_rpt_Service AS v_rpt_Service_1
       WHERE (date_entered > = DateAdd(Day, DateDiff(Day, 0, GetDate()) - (180 / 2), 0))
       GROUP BY { fn WEEK(date_entered) }, { fn YEAR(date_entered) }) AS e ON d.weekClosed = e.weekEntered AND d.yearClosed = e.yearEntered
) as f ON c.yearClosed = f.yearClosed AND c.weekClosed = f.weekClosed AND c.weekEntered = f.weekEntered AND c.yearEntered = f.yearEntered AND c.period = f.period
GROUP BY c.period, resolved_half1,resolved_half2,opened_half1,opened_half2,c.yearClosed,c.weekClosed
ORDER BY row

このコードは、ハードコードされた 180 日の値を使用します。私はまだ変数を使用して日数を選択できるようにする必要があり (0 による除算エラーを発生させずに)、コードを本当にクリーンアップする必要があります。誰かが私のためにこれらの 2 つのことを行うことができれば (私は SQL が得意ではありません)、報奨金は彼らのものです。

画像:

チャート

于 2012-04-09T18:17:30.997 に答える
0

これでうまくいくと思います-実際のサンプルデータを投稿しない場合は、微調整して修正できるかどうかを確認します。

DECLARE @noOfDays INT
SET @noofdays = 180

;WITH tickets AS
(
SELECT DISTINCT
DATENAME(YEAR,date_closed) + RIGHT('000' + CAST(DATEPART(WEEK,date_closed) AS VARCHAR(5)),3) as Period
,ticket_nbr
,1 as ticket_type --resolved
FROM v_rpt_Service
WHERE (date_closed >= DateAdd(Day, DateDiff(Day, 0, GetDate()) - @NoOfDays, 0)) 
UNION ALL
SELECT DISTINCT
DATENAME(YEAR,date_closed) + RIGHT('000' + CAST(DATEPART(WEEK,date_closed) AS VARCHAR(5)),3) as Period
,ticket_nbr
,0 as ticket_type --opened
FROM v_rpt_Service
WHERE  (date_entered > = DateAdd(Day, DateDiff(Day, 0, GetDate()) - @NoOfDays, 0)) 
)
,tickets2 AS
(
SELECT
Period
,SUM(CASE WHEN ticket_type = 0 THEN 1 ELSE 0 END) as opened
,SUM(CASE WHEN ticket_type = 1 THEN 1 ELSE 0 END) as closed
FROM tickets
GROUP BY
Period
)
,tickets3 AS
(
SELECT
Period
,row_number() OVER (ORDER BY period ASC) as row
,opened
,closed
,COUNT(period) OVER() as base
,SUM(opened) OVER () as [Sumopened]
,SUM(opened * opened) OVER () as [Sumopened^2]
,SUM(opened * closed) OVER () as [Sumopenedclosed]
,SUM(closed) OVER () as [Sumclosed]
,SUM(closed * closed) OVER () as [Sumclosed^2]
,SUM(opened * closed) OVER () * COUNT(period) OVER () AS [nSumopenedclosed]
,SUM(opened) OVER () * SUM(closed) OVER () AS [Sumopened*Sumclosed]
,SUM(opened * opened) OVER () * COUNT(period) OVER () AS [nSumopened^2]
,SUM(opened) OVER () * SUM(opened) OVER () as [Sumopened*Sumopened]
FROM tickets2
)
--Formula for linear regression is Y = A + BX
SELECT
period
,opened
,closed
,((1.0 / base) * [Sumclosed]) - 
([Sumopenedclosed] - ([Sumopened*Sumclosed] / base)) / ([Sumopened^2] - ([Sumopened*Sumopened] / base)) *((1.0 / base) * [Sumopened]) 
+ row * ([Sumopenedclosed] - ([Sumopened*Sumclosed] / base)) / ([Sumopened^2] - ([Sumopened*Sumopened] / base))  
AS trend_point
,((1.0 / base) * [Sumclosed]) - 
([Sumopenedclosed] - ([Sumopened*Sumclosed] / base)) / ([Sumopened^2] - ([Sumopened*Sumopened] / base)) *((1.0 / base) * [Sumopened]) AS A
,([Sumopenedclosed] - ([Sumopened*Sumclosed] / base)) / ([Sumopened^2] - ([Sumopened*Sumopened] / base)) as B
from tickets3
于 2012-04-11T08:13:16.943 に答える