4

次のようなスキーマがあります(簡略化):

CREATE TABLE MyTable (
   DateTimeOffset HitDate NOT NULL,
   IpAddress varchar(15)
)

サンプル行は次のようになります。

'7/10/2013 8:05:29 -07:00' '111.222.333.444'

毎日 (たとえば、2013 年 7 月 10 日) の一意の IpAddresses の数を取得するクエリを作成しようとしています。実際、その部分はかなり簡単で、そのためのクエリをすでに作成しています。IpAddressesただし、このクエリでは、現在の日付より前に存在したことのない一意の数が必要です。デート直前でもデート後でも構いません。

たとえば、次のデータがあり、これがすべてだとします。

'7/10/2013 8:05:29 -07:00' '111.222.333.444'
'7/10/2013 12:05:29 -07:00' '111.222.333.222'
'7/9/2013 9:05:29 -07:00' '111.222.333.444'
'7/9/2013 10:05:29 -07:00' '111.222.333.555'
'7/8/2013 11:05:29 -07:00' '111.222.333.222'
'7/8/2013 4:05:29 -07:00' '111.222.333.555'

クエリは次のように出力する必要があります。

'7/8/2013' 2 (neither IpAddress existed before this date so both are new)
'7/9/2013' 1 (only one of the IpAddresses is new - the one ending in '444')
'7/10/2013' 0 (both IpAddresses had existed before this date)

ターゲット データベースはSQL Server 2012です。最初に SQL ステートメントを正しく作成した人に 100 ポイントの報奨金を提供します。

4

9 に答える 9

1

[編集 - 代わりに DateTimeOffset を使用するように変更]

ベースMyTableの作成から始めて、次のことを思いつきました。

-- Test data creation to match schema & examples

create TABLE MyTable (
   HitDate DateTimeOffset  NOT NULL,
   IpAddress varchar(15)
)

insert into MyTable values ('7/10/2013 8:05:29 -07:00', '111.222.333.444')
insert into MyTable values ('7/10/2013 12:05:29 -07:00', '111.222.333.222')
insert into MyTable values ('7/9/2013 9:05:29 -07:00', '111.222.333.444')
insert into MyTable values ('7/9/2013 10:05:29 -07:00', '111.222.333.555')
insert into MyTable values ('7/8/2013 11:05:29 -07:00', '111.222.333.222')
insert into MyTable values ('7/8/2013 4:05:29 -07:00', '111.222.333.555')

-- actual solution starts here

create TABLE #MyTable (
   HitDate date,
   IpAddress varchar(15)
)

-- populate data into required format for main query

insert into #MyTable SELECT HitDate, IpAddress FROM MyTable

-- main query

select distinct convert(varchar(10), HitDate, 101) HitDate, ISNULL(dateCounts.counter, 0) NewIPAddresses
from #MyTable mainDates
left outer join 
    (
        select main.HitDate dateValue, count(*) counter from
            #MyTable main
            left outer join #MyTable sub on main.IpAddress = sub.IpAddress and main.HitDate > sub.HitDate
            where sub.IpAddress is null
            group by main.HitDate
    ) dateCounts on dateCounts.dateValue = HitDate

これは次を与えます:

    HitDate        NewIPAddresses 
    -------------- --------------
    07/08/2013     2
    07/09/2013     1
    07/10/2013     0
于 2013-07-10T12:27:59.003 に答える
1

これを試して

SELECT 
  CONVERT(DATE,T1.[HitDate]) AS [HitDate]
  ,SUM(CASE WHEN T2.[IpAddress] IS NULL THEN 1 ELSE 0 END) AS IpAddress
FROM 
    YourTableName T1 
LEFT JOIN
    YourTableName T2 ON T1.IpAddress = T2.IpAddress
AND 
    T1.[HitDate] > T2.[HitDate]
GROUP BY CONVERT(DATE,T1.[HitDate])

SQL フィドルのデモ

data.stackexchange デモ

出力

HitDate    IpAddress
2013-07-08  2
2013-07-09  1
2013-07-10  0
于 2013-07-15T05:58:34.830 に答える
0

これを試して:

    SELECT CONVERT(DATE, mt.HitDate) AS hitDate
           , COUNT(firstDate.ipAddress) AS newIPAddresses
      FROM MyTable mt
 LEFT JOIN (SELECT IpAddress, MIN(HitDate) AS FirstHitDate
              FROM MyTable
          GROUP BY IpAddress) firstDate
          ON mt.HitDate = firstDate.FirstHitDate
          AND mt.IpAddress = firstDate.IpAddress
  GROUP BY CONVERT(DATE, mt.HitDate)
  ORDER BY 1

出力:

hitDate     newIPAddress
2013-07-08  2
2013-07-09  1
2013-07-10  0
于 2013-07-15T05:38:34.570 に答える
0

目的の結果を得るために、T-SQL でカーソルを使用しました。

以下のコード:

INSERT INTO MyTable(HitDate, IpAddress) values ('7/10/2013 8:05:29 -07:00', '111.222.333.444')
INSERT INTO MyTable(HitDate, IpAddress) VALUES('7/10/2013 12:05:29 -07:00',     '111.222.333.222')
INSERT INTO MyTable(HitDate, IpAddress) VALUES('7/9/2013 9:05:29 -07:00', '111.222.333.444')
INSERT INTO MyTable(HitDate, IpAddress) VALUES('7/9/2013 10:05:29 -07:00', '111.222.333.555')
INSERT INTO MyTable(HitDate, IpAddress) VALUES('7/8/2013 11:05:29 -07:00', '111.222.333.222')
INSERT INTO MyTable(HitDate, IpAddress) VALUES('7/8/2013 4:05:29 -07:00', '111.222.333.555')


DECLARE @HitDate DATE

DECLARE cCursor CURSOR FAST_FORWARD LOCAL
FOR
SELECT 
    DISTINCT CAST(HitDate AS DATE)
FROM 
    MyTable
ORDER BY
    CAST(HitDate AS DATE) ASC

OPEN cCursor

FETCH NEXT FROM cCursor INTO @HitDate
WHILE (@@FETCH_STATUS = 0)
BEGIN

    SELECT @HitDate, COUNT(IpAddress)
    FROM MyTable
    WHERE IpAddress NOT IN (SELECT IpAddress FROM MyTable WHERE HitDate < @HitDate) AND     CAST(HitDate AS DATE) = @HitDate

    FETCH NEXT FROM cCursor INTO @HitDate
END

CLOSE cCursor
DEALLOCATE cCursor

出力は次のとおりです。

2013-07-08 2
2013-07-09 1
2013-07-10 0

于 2013-07-15T04:35:45.157 に答える