按月分组数据

时间:2013-03-06 20:26:47

标签: sql sql-server group-by

我想根据YEAR-MONTH的销售结果进行分组。我当前查询结果如下:

SELECT Cast(Year(s.datekey) AS VARCHAR(4)) + '-' 
       + Cast(Month(s.datekey) AS VARCHAR(2)) AS Mjesec, 
       e.employeekey, 
       Sum(s.totalcost)                       AS SalesAmount 
FROM   factsales s 
       INNER JOIN dimstore st 
               ON s.storekey = st.storekey 
       INNER JOIN dimemployee e 
               ON e.employeekey = st.storemanager 
WHERE  s.datekey BETWEEN '2007-01-01' AND '2007-01-05' 
GROUP  BY e.employeekey, 
          Cast(Year(s.datekey) AS VARCHAR(4)) + '-' 
          + Cast(Month(s.datekey) AS VARCHAR(2)) 
ORDER  BY employeekey 

我想知道是否还有其他更好,更优雅的方法来达到相同的效果?也许,c#中DateTime更友好的格式?

2 个答案:

答案 0 :(得分:1)

执行:

SELECT CONVERT(CHAR(7),s.DateKey,120) AS Mjesec....
FROM ....
GROUP BY CONVERT(CHAR(7),s.DateKey,120)....
ORDER BY EmployeeKey

答案 1 :(得分:1)

通过使用日期数学而不是转换为字符串来更有效地剥离时间。将特定的字符串格式保留到最后也更有效(或者更好的是,使用Format()在C#中执行此操作)。

;WITH c AS
(
  SELECT m = DATEADD(MONTH, DATEDIFF(MONTH, 0, s.datekey), 0),
   e.employeekey, s.totalcost
  FROM dbo.factsales AS s
  INNER JOIN dbo.dimstore AS st
  ON s.storekey = st.storekey
  INNER JOIN dimemployee AS e
  ON e.employeekey = st.storemanager
  WHERE s.datekey >= '20070101' AND s.datekey < '20070106'
),
d AS
(
  SELECT m, employeekey, SalesAmount = SUM(totalcost)
    FROM c
    GROUP BY m, employeekey
)
SELECT 
  Mjesec = CONVERT(CHAR(7), m, 120), 
  employeekey, 
  SalesAmount
FROM d
ORDER BY employeekey;

如果您可以在应用中进行格式化,则可以将其折叠为:

;WITH c AS
(
  SELECT m = DATEADD(MONTH, DATEDIFF(MONTH, 0, s.datekey), 0),
   e.employeekey, s.totalcost
  FROM dbo.factsales AS s
  INNER JOIN dbo.dimstore AS st
  ON s.storekey = st.storekey
  INNER JOIN dimemployee AS e
  ON e.employeekey = st.storemanager
  WHERE s.datekey >= '20070101' AND s.datekey < '20070106'
)
SELECT Mjesec = m, employeekey, SalesAmount = SUM(totalcost)
  FROM c
  GROUP BY m, employeekey
  ORDER BY employeekey;

甚至:

  SELECT Mjesec = DATEADD(MONTH, DATEDIFF(MONTH, 0, s.datekey), 0),
   e.employeekey, s.totalcost
  FROM dbo.factsales AS s
  INNER JOIN dbo.dimstore AS st
  ON s.storekey = st.storekey
  INNER JOIN dimemployee AS e
  ON e.employeekey = st.storemanager
  WHERE s.datekey >= '20070101' AND s.datekey < '20070106'
  GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, s.datekey, 0), 0), e.employeekey
  ORDER BY employeekey;