0

私の問題:

表: trans_detail :

PhoneNo | Datetime
01234   |  2013-01-05 20:40:10
01245   |  2013-04-02 21:00:13
05678   |  2013-04-16 01:24:07
04567   |  2013-07-23 07:00:00
etc     |  etc

phoneNo過去 X か月 (X 月は 1 ~ 12 の任意の月) のすべての月に少なくとも 1 回表示されるものをすべて取得したいと考えています。

例: すべての電話番号を取得します。過去 3 か月間、毎月少なくとも 1 回表示されます。

SQL Server 2005 を使用しています。

4

2 に答える 2

2

これは、あなたが望むものに近い簡単なクエリです:

select PhoneNo
from trans_detail d
where d.datetime >= dateadd(mm, -@X, getdate())
group by PhoneNo
having count(distinct year(datetime)*12+month(datetime)) = @X

このwhere句は、過去の月の行のみが含まれるようにデータをフィルター処理します@X。このhaving句は、個別の月の数を数えることによって、各月がデータに含まれていることを確認します。

上記のバージョンのクエリでは、暦月を意味していると想定しています。したがって、境界条件の問題があります。6 月 16 日に実行すると、1 か月前にさかのぼって、5 月 16 日以降の電話番号が少なくとも 1 回表示されていることを確認します。数字が 2 回 (5 月に 1 回と 6 月に 1 回) 表示されることを主張したいのか、1 回 (期間中に 1 回) 表示されることを主張したいのか、私にはよくわかりません。これに対する解決策は、現在の日付を前の月末に戻すことです。

select PhoneNo
from trans_detail d cross join
     (select cast(getdate() - day(getdate) + 1 as date) as FirstOfMonth const
where d.datetime >= dateadd(mm, -@X, FirstOfMonth) and
      d.datetime < FirstOfMonth
group by PhoneNo
having count(distinct year(datetime)*12+month(datetime)) = @X
于 2013-06-16T13:50:28.933 に答える
1

ここにあります。最初の 2 つの CTE は過去 X か月を検索して準備するもので、3 つ目の CTE は電話番号と月ごとにデータをグループ化するものです。最後に、2つを結合して、一致する行の数が月数に等しい場所を返します。

DECLARE @months INT
SET @Months = 3

;WITH CTE_Dates AS 
(
    SELECT GETDATE() AS Dt
    UNION ALL
    SELECT DATEADD(MM,-1,Dt) FROM CTE_Dates
    WHERE DATEDIFF(MM, Dt,GETDATE()) < @months-1 
)
, CTE_Months AS 
(
    SELECT MONTH(Dt) AS Mn, YEAR(Dt) AS Yr FROM CTE_Dates
)
, CTE_Trans AS
(
    SELECT PhoneNo, MONTH([Datetime]) AS Mn, YEAR([Datetime]) AS Yr FROM dbo.trans_detail
    GROUP BY PhoneNo, MONTH([Datetime]), YEAR([Datetime])
)
SELECT PhoneNo FROM CTE_Months m
LEFT JOIN CTE_Trans t ON m.Mn = t.Mn AND m.Yr = t.Yr
GROUP BY PhoneNo
HAVING COUNT(*) = @months

SQLFiddle デモ- 過去 3 か月間に一致するデータを追加

于 2013-06-16T14:01:36.493 に答える