对于模糊的标题感到抱歉!
我正在构建一个Web过滤器,用户可以使用MS-SQL 2012单击选项并过滤结果
我遇到的问题是我在为构建过滤器而选择的每个选项上运行4个查询,并为结果运行1个查询。
忽略如何对其进行最佳编码,以便每次都不必重新加载过滤器查询,我需要帮助我如何合并产生过滤器选项的4个查询并计入1。
语法的核心是相同的,其中大多数逻辑基于过滤的选择提取结果。但是,我仍然需要生成带有计数的过滤器。
select datePart(yy,p.startDate) year, count(p.personId) itemCount
from person p
where p.field1 = something
and p.field2 = somethingElse...
有没有办法运行核心并生成过滤器列表并计算(见下文)所有的一个而不是单独执行每个过程?
下面是2个过滤器的示例,但是还有其他类似的过滤器,可以根据现有数据生成列表,也可以根据特定日期之前,之间和之后生成列表。
--Filter 1 to get years and counts
with annualList as
(
select a.year
from table a
where a.year > 2000
)
select al.year, isnull(count,0) itemCount
from annualList al
left join (
select datePart(yy,p.startDate) year, count(p.personId) itemCount
from person p
where p.field1 = something
and p.field2 = somethingElse...
) group by datePart(yy,p.startDate) persons
on al.year = persons.year
order by al.year desc;
--filter 2 to get group stats
select anotherList.groupStatus, groupStatusCounts.itemCount
from (
select 'Child' as groupStatus
union all
select 'Adult' as groupStatus
union all
select 'Pensioner' as groupStatus
) anotherList
left join (
SELECT personStatus.groupStatus, count(personStatus.personId) itemCount
FROM ( select p.personId
case when (p.age between 1 and 17) then 'Child'
case when (p.age between 18 and 67) then 'Adult'
case when (p.age > 65) then 'Pensioner'
end as groupStatus
FROM person p
--and some other syntax to calculate the age...
where p.field1 = something
and p.field2 = somethingElse exactly as above query...
) personStatus
GROUP BY personStatus.groupStatus
) groupStatusCounts
ON anotherList.groupStatus = groupStatusCounts.groupStatus
例如,使用下面的数据集,从regDate和我使用的组将能够获得2010-2014的年份列表(上面的filter1代码)。
使用dataofbirth我需要计算' groupStatus使用案例。从数据生成数据中可以看出,我没有任何记录可以识别养老金领取者因此我编写过滤器2的方式(参见上面的代码),它会给我提供我需要的过滤器,即使我没有&# 39; t有数据来代表它。
试图在SQL Fiddle上添加代码,不幸的是它昨晚失败了
INSERT INTO personTable
([PersonID], [dateOfBirth], [regDate])
VALUES
(1, '1979-01-01 00:00:00', '2010-01-01 00:00:00'),
(2, '1979-01-01 00:00:00', '2010-01-01 00:00:00'),
(3, '1979-01-01 00:00:00', '2011-01-01 00:00:00'),
(4, '1979-01-01 00:00:00', '2011-01-01 00:00:00'),
(5, '1979-01-01 00:00:00', '2012-01-01 00:00:00'),
(6, '1979-01-01 00:00:00', '2012-01-01 00:00:00'),
(7, '1984-01-01 00:00:00', '2012-01-01 00:00:00'),
(8, '1992-01-01 00:00:00', '2012-01-01 00:00:00'),
(9, '2000-01-01 00:00:00', '2013-01-01 00:00:00'),
(10, '2010-01-01 00:00:00', '2014-01-01 00:00:00')
结果想要结束,我需要根据Fiddle
中显示的结果看起来像这样filter | Year | groupStatus
-----------+-----------+--------
2010 | 0 | null
2011 | 2 | null
2012 | 3 | null
2013 | 0 | null
2014 | 3 | null
child | null | 2
adult | null | 6
pensioner | null | 0
提前感谢你
答案 0 :(得分:0)
我可能已经大量误解了这个要求,但我怀疑你想要使用GROUPING SETS
。作为一个简单示例(忽略您的特定过滤器),想象一下以下简单数据集:
PersonID | GroupStatus | Year
---------+-------------+--------
1 | Adult | 2013
2 | Adult | 2013
3 | Adult | 2014
4 | Adult | 2014
5 | Adult | 2014
6 | Child | 2012
7 | Child | 2014
8 | Pensioner | 2012
9 | Pensioner | 2013
10 | Pensioner | 2013
从我收集的内容中,您试图从这些数据中获取2个不同的摘要,而不重复查询,例如。
GroupStatus | ItemCount
------------+-----------
Adult | 5
Child | 2
Pensioner | 3
和
Year | ItemCount
------------+-----------
2012 | 2
2013 | 4
2014 | 4
您可以使用以下方法在单个数据集中获取此内容:
SELECT Year,
GroupStatus,
ItemCount = COUNT(*)
FROM T
GROUP BY GROUPING SETS ((Year), (GroupStatus));
这将产生一个数据集:
YEAR GROUPSTATUS ITEMCOUNT
------------------------------------
NULL Adult 5
NULL Child 2
NULL Pensioner 3
2012 NULL 2
2013 NULL 4
2014 NULL 4
如果您还希望包含完整数据,则只需添加包含所有字段的分组集,例如(PersonID, Year, GroupStatus)
。
<强> Examples on SQL Fiddle 强>
编辑
以下查询给出了您请求的输出:
WITH AllValues AS
( SELECT TOP (DATEPART(YEAR, GETDATE()) - 2009)
Filter = CAST(2009 + ROW_NUMBER() OVER(ORDER BY object_id) AS VARCHAR(15)),
FilterType = 'Year'
FROM sys.all_objects o
UNION ALL
SELECT Filter, 'GroupStatus'
FROM (VALUES ('child'), ('Adult'), ('Pensioner')) T (Filter)
)
SELECT v.Filter,
[Year] = CASE WHEN v.FilterType = 'Year' THEN ISNULL(data.ItemCount, 0) END,
GroupStatus = CASE WHEN v.FilterType = 'GroupStatus' THEN ISNULL(data.ItemCount, 0) END
FROM AllValues AS v
LEFT JOIN
( SELECT [Year] = DATENAME(YEAR, t.RegDate),
Age = a.Name,
ItemCount = COUNT(*)
FROM T
LEFT JOIN
(VALUES
(0, 18, 'Child'),
(18, 65, 'adult'),
(65, 1000000, 'pensioner')
) a (LowerValue, UpperValue, Name)
ON a.LowerValue <= DATEDIFF(HOUR, T.dateofbirth, GETDATE()) / 8766.0
AND a.UpperValue > DATEDIFF(HOUR, T.dateofbirth, GETDATE()) / 8766.0
WHERE T.PersonID > 2
GROUP BY GROUPING SETS ((DATENAME(YEAR, t.RegDate)), (a.Name))
) AS data
ON ISNULL(data.[Year], data.Age) = v.Filter;
<强> Example on SQL Fiddle 强>