所以我不太清楚为什么今天早上这个给我这么多麻烦。我打算把它归结为星期五早上。 :)我们的目标是按频率计算该时期内拥有零照片,三张照片和六张或更多照片的房地产物业数量。我需要一个看起来像这样的结果集(注意:“三列或更多列不应该包含正好六列的那些 - 最多可以有六张照片):
Period Start Period End Zero ThreeOrMore ExactlySix
------------------------------------------------------------------------
1/1/2011 1/7/2011 15 132 512
1/8/2011 1/14/2011 44 123 402
我提出了日期,我实际上已经生成了正确的周开始/结束日期。
我的“属性”表格如下:
PropertyRecId Other fields
-----------------------------
12345 <blah>
56789 <blah>
我的“PropertyPhoto”表格如下(仅包含必要的字段):
PropertyPhotoId PropertyRecId CreatedOn
---------------------------------------------
1 12345 3/1/2011
2 12345 3/1/2011
etc...
我正在使用下面的查询,但我并不感激它。我只需要完成目标。请记住,使用我现有的查询,我无法访问顶级选择中的“Propery”记录。我尝试将查询放入创建PeriodStart和PeriodEnd的辅助选择中,但这只会导致不同的问题。
DECLARE @DateStart datetime
DECLARE @DateEnd datetime
SET @DateStart = '1/1/2011'
SET @DateEnd = '12/31/2011'
DECLARE @Frequency varchar(50)
SET @Frequency = 'month'
SELECT
PeriodStart,
PeriodEnd,
??? As Zero,
??? As ThreeOrMore,
??? As ExactlySix
FROM (
SELECT
PeriodStart = CASE @Frequency
WHEN 'day' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, CreatedOn))
WHEN 'week' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(DAY, 1 - DATEPART(WEEKDAY, CreatedOn), CreatedOn)))
WHEN 'month' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(MONTH, DATEDIFF(MONTH, 0, CreatedOn), 0)))
WHEN 'quarter' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, CreatedOn), 0)))
WHEN 'year' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(YEAR, DATEDIFF(YEAR, 0, CreatedOn), 0)))
END,
PeriodEnd = CASE @Frequency
WHEN 'day' THEN DATEADD(s, -1, DATEADD(day, 1, DATEDIFF(DAY, 0, CreatedOn)))
WHEN 'week' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, 7 - DATEPART(WEEKDAY, CreatedOn), CreatedOn))))
WHEN 'month' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, CreatedOn) + 1, 0)))))
WHEN 'quarter' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, CreatedOn) + 1, 0)))))
WHEN 'year' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, CreatedOn) + 1, 0)))))
END
FROM Property P
WHERE CreatedOn BETWEEN @DateStart AND @DateEnd
) s
GROUP BY
PeriodStart,
PeriodEnd
ORDER BY PeriodStart
答案 0 :(得分:4)
您可以使用子查询中的over
函数来获取此函数,并在外部选择case
语句中添加'em:
DECLARE @Frequency varchar(50)
SET @Frequency = 'month'
SELECT
PeriodStart,
PeriodEnd,
SUM(case when s.PhotoCount = 0 then 1 else 0 end) As Zero,
SUM(case when s.PhotoCount between 3 and 5 then 1 else 0 end) As ThreeOrMore,
SUM(case when s.PhotoCount = 6 then 1 else 0 end) As ExactlySix
FROM (
SELECT
PeriodStart =
CASE @Frequency
WHEN 'day' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, CreatedOn))
WHEN 'week' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(DAY, 1 - DATEPART(WEEKDAY, CreatedOn), CreatedOn)))
WHEN 'month' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(MONTH, DATEDIFF(MONTH, 0, CreatedOn), 0)))
WHEN 'quarter' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, CreatedOn), 0)))
WHEN 'year' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(YEAR, DATEDIFF(YEAR, 0, CreatedOn), 0)))
END,
PeriodEnd =
CASE @Frequency
WHEN 'day' THEN DATEADD(s, -1, DATEADD(day, 1, DATEDIFF(DAY, 0, CreatedOn)))
WHEN 'week' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, 7 - DATEPART(WEEKDAY, CreatedOn), CreatedOn))))
WHEN 'month' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, CreatedOn) + 1, 0)))))
WHEN 'quarter' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, CreatedOn) + 1, 0)))))
WHEN 'year' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, CreatedOn) + 1, 0)))))
END,
p.PropertyRecId,
COUNT(ph.PropertyPhotoId) over (partition by p.PropertyRecId) as PhotoCount
FROM
Property P
left join PropertyPhoto ph on
p.PropertyRecId = ph.PropertyRecId
WHERE
CreatedOn BETWEEN @DateStart AND @DateEnd
) s
GROUP BY
PeriodStart,
PeriodEnd
ORDER BY
PeriodStart
您也可以使用传统的group by
进行内部查询,但我爱我一些over
并希望引起您的注意:
SELECT
PeriodStart =
CASE @Frequency
WHEN 'day' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, CreatedOn))
WHEN 'week' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(DAY, 1 - DATEPART(WEEKDAY, CreatedOn), CreatedOn)))
WHEN 'month' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(MONTH, DATEDIFF(MONTH, 0, CreatedOn), 0)))
WHEN 'quarter' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, CreatedOn), 0)))
WHEN 'year' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(YEAR, DATEDIFF(YEAR, 0, CreatedOn), 0)))
END,
PeriodEnd =
CASE @Frequency
WHEN 'day' THEN DATEADD(s, -1, DATEADD(day, 1, DATEDIFF(DAY, 0, CreatedOn)))
WHEN 'week' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, 7 - DATEPART(WEEKDAY, CreatedOn), CreatedOn))))
WHEN 'month' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, CreatedOn) + 1, 0)))))
WHEN 'quarter' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, CreatedOn) + 1, 0)))))
WHEN 'year' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, CreatedOn) + 1, 0)))))
END,
p.PropertyRecId,
COUNT(ph.PropertyPhotoId) over (partition by p.PropertyRecId) as PhotoCount
FROM
Property P
left join PropertyPhoto ph on
p.PropertyRecId = ph.PropertyRecId
WHERE
CreatedOn BETWEEN @DateStart AND @DateEnd
GROUP BY
p.PropertyRecId,
p.CreatedOn
答案 1 :(得分:1)
这有效吗?:
--1 : Make a lookup-up table of period start/end
CREATE TABLE #PERIODS (
[Period Start] datetime
, [Period End] datetime
);
DECLARE @firstDay datetime
DECLARE @rowid int
SET @firstDay = '2011-01-01'
WHILE @firstDay < '2012-01-01'
BEGIN
INSERT INTO #PERIODS VALUES ( @firstDay, DATEADD(DAY,6,@firstDay));
SET @firstDay = @firstDay + 7
END
GO
-- 2 Count the photos per property per period
CREATE TABLE #PHOTOCOUNT (
[Period Start] datetime
, [Period End] datetime
, PropertyRecId int
, PhotoCount int
);
GO
INSERT INTO #PHOTOCOUNT
SELECT
PD.[Period Start]
, PD.[Period End]
, Property.PropertyRecId
, COUNT(PropertyPhoto.PropertyPhotoId) AS PhotoCount
FROM
#PERIODS AS PD,
Property
LEFT JOIN PropertyPhoto
ON Property.PropertyRecId = PropertyPhoto.PropertyRecId
WHERE
PropertyPhoto.PropertyRecId Is Null
OR PropertyPhoto.CreatedOn BETWEEN PD.[Period Start] AND PD.[Period End]
GROUP BY
PD.[Period Start]
, PD.[Period End]
, Property.PropertyRecId;
GO
-- 3 Categorize by 0, 3 to 5, 6
SELECT
[Period Start]
, [Period End]
, SUM(RANGES.Zero) AS Zero
, SUM(RANGES.ThreeToFive) AS ThreeToFive
, SUM(RANGES.Six) AS Six
FROM (
SELECT
[Period Start]
, [Period End]
, Zero = CASE WHEN PhotoCount = 0 THEN 1 ELSE 0 END
, ThreeToFive = CASE WHEN PhotoCount BETWEEN 3 AND 5 THEN 1 ELSE 0 END
, Six = CASE WHEN PhotoCount = 6 THEN 1 ELSE 0 END
FROM #PHOTOCOUNT
) RANGES
GROUP BY
[Period Start]
, [Period End]
;
DROP TABLE #PERIODS;
DROP TABLE #PHOTOCOUNT;