1

我需要一些帮助来获取每个地区所有 projectTypes 的每月项目计数。我已经尝试了以下语句,但它没有返回我需要的内容。以下语句的问题在于,仅当该月有计数时,它才返回 projectType。如果月份没有计数,我需要返回零。任何帮助深表感谢。

SELECT r.region, pt.projectType, count(p.id) as totalCount, p.postedOn as monthCount
FROM region r cross join ProjectTypes pt left join projects p on p.regionID = r.id and pt.id = p.TypeID 
WHERE year(p.postedOn) = '2012' 
group by r.region, pt.projectType, p.postedOn 
order by r.region

请在此处提供示例:http ://sqlfiddle.com/#!3/6680f/18

地区:
-------------------------
编号 | 地区 |
-------------------------
1 | 东 |
-------------------------
2 | 中西部 |
-------------------------
3 | 西 |
-------------------------


项目类型:
-------------------------
编号 | 项目类型 |
-------------------------
1 | 网页设计 |
-------------------------
2 | 数据库 |
-------------------------
3 | 发展 |
-------------------------


项目:
-------------------------------------------------- ----------------------
编号 | 项目名称 | 地区ID | 项目类型ID | 发表于 |
-------------------------------------------------- ----------------------
1 | 项目 1 | 1 | 2 | 2012-09-02 |
-------------------------------------------------- ----------------------
2 | 项目 2 | 2 | 2 | 2012-09-02 |
-------------------------------------------------- ----------------------
3 | 项目 3 | 1 | 1 | 2012-09-02 |
-------------------------------------------------- ----------------------
4 | 项目 4 | 3 | 2 | 2012-09-02 |
-------------------------------------------------- ----------------------
5 | 项目 5 | 3 | 1 | 2012-10-02 |
-------------------------------------------------- ----------------------
6 | 项目 6 | 3 | 2 | 2012-10-02 |
-------------------------------------------------- ----------------------
7 | 项目 7 | 3 | 3 | 2012-10-02 |
-------------------------------------------------- ----------------------
8 | 项目 8 | 2 | 3 | 2012-10-02 |
-------------------------------------------------- ----------------------
9 | 项目 9 | 1 | 2 | 2012-10-02 |
-------------------------------------------------- ----------------------
10 | 项目 10 | 1 | 2 | 2012-10-02 |
-------------------------------------------------- ----------------------


期望的结果:
-------------------------------------------------- --------
地区 | 项目类型 | 总数 | 月数 |
-------------------------------------------------- --------
东 | 网页设计 | 1 | 九月 |
-------------------------------------------------- --------
东 | 数据库 | 1 | 九月 |
-------------------------------------------------- --------
东 | 发展 | 0 | 九月 |
-------------------------------------------------- --------
中西部 | 网页设计 | 0 | 九月 |
-------------------------------------------------- --------
中西部 | 数据库 | 1 | 九月 |
-------------------------------------------------- --------
中西部 | 发展 | 0 | 九月 |
-------------------------------------------------- --------
西 | 网页设计 | 0 | 九月 |
-------------------------------------------------- --------
西 | 数据库 | 1 | 九月 |
-------------------------------------------------- --------
西 | 发展 | 0 | 九月 |
-------------------------------------------------- --------
东 | 网页设计 | 0 | 十月 |
-------------------------------------------------- --------
东 | 数据库 | 2 | 十月 |
-------------------------------------------------- --------
东 | 发展 | 0 | 十月 |
-------------------------------------------------- --------
中西部 | 网页设计 | 0 | 十月 |
-------------------------------------------------- --------
中西部 | 数据库 | 0 | 十月 |
-------------------------------------------------- --------
中西部 | 发展 | 1 | 十月 |
-------------------------------------------------- --------
西 | 网页设计 | 1 | 十月 |
-------------------------------------------------- --------
西 | 数据库 | 1 | 十月 |
-------------------------------------------------- --------
西 | 发展 | 1 | 十月 |
-------------------------------------------------- --------
4

2 回答 2

1

WITH 块定义了所需的月份(或者更确切地说,每个月的第一天)的虚拟表。这会延长您的 CROSS JOIN 以给您所有的月份。

;WITH months(startdate) AS (
     SELECT CAST('20120901' AS date)
  UNION ALL
     SELECT dateadd(m,1,startdate)
       FROM months
      WHERE startdate < '20121001'
)

    SELECT r.region,
           pt.projectType,
           count(p.id) totalCount,
           DATENAME(Month,m.startdate) monthCount
      FROM region r
CROSS JOIN ProjectTypes pt
CROSS JOIN months m
 LEFT JOIN projects p ON p.regionID = r.id
       AND pt.id = p.TypeID
       AND p.postedOn >= m.startdate
       AND p.postedOn <  dateadd(m,1,m.startdate)
  GROUP BY r.region, pt.projectType, m.startdate
  ORDER BY m.startdate, region, projecttype
    OPTION (maxrecursion 0);

我把这个应用到你的小提琴上

对于 SQL Server 2000,或者实际上是为了性能,将表创建Months为适当的表,并用从 1999 年到 2169 年的月份填充它,例如

CREATE TABLE Months (
  startdate datetime -- the first day of month
    primary key
);
insert Months
select DateAdd(M,Number,'19990101')
from master..spt_values
where type='P'
GO

然后,只需使用月份表的条件选择您需要的月份范围,即如下:

    SELECT r.region,
           pt.projectType,
           count(p.id) totalCount,
           DATENAME(Month,m.startdate) monthCount
      FROM region r
CROSS JOIN ProjectTypes pt
      JOIN months m on m.startdate between '20120901' and '20121001'
 LEFT JOIN projects p ON p.regionID = r.id
       AND pt.id = p.TypeID
       AND p.postedOn >= m.startdate
       AND p.postedOn <  dateadd(m,1,m.startdate)
  GROUP BY r.region, pt.projectType, m.startdate
  ORDER BY m.startdate, region, projecttype;

更新的 SQL Fiddle

于 2012-10-09T00:53:18.457 回答
1

嗨,我的回答需要你桌子上的所有月份并制作套装。

SELECT
r.region
,pt.projectType
,(SELECT Count(*)
  FROM Projects pp
    WHERE pt.id = pp.TypeID
      AND r.id = pp.regionID
      AND DATENAME(MONTH, p.postedOn)=DATENAME(MONTH, pp.postedOn)) AS COUNT
,DATENAME(MONTH, p.postedOn) AS monthName
FROM ProjectTypes pt, region r,
(SELECT DISTINCT postedOn FROM Projects )p
ORDER BY r.region, DATENAME(MONTH, p.postedOn)

SQLFiddle 示例

于 2012-10-09T06:38:32.573 回答