需要在SQL Server 2012查询中对记录进行分组,但要点击“不在聚合中的字段”问题

时间:2015-08-05 13:45:55

标签: tsql sql-server-2012 aggregate

我有这个查询

SELECT Count(BATCHDETAIL.SERIALNUMBER) AS CountOfSERIALNUMBER,
IIf(datepart(month,[FirstPaid])>7 And datepart(month,[FirstPaid]) In (7,8,9) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q1',
IIf(datepart(month,[FirstPaid])>7 And datepart(month,[FirstPaid]) In (10,11,12) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q2',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (1,2,3) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q3',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (4,5,6) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q4',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (7,8,9) And datepart(year,[FirstPaid])=Format(DateAdd(year,-1,getdate()),'yyyy'),'Q1',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (10,11,12) And datepart(year,[FirstPaid])=Format(DateAdd(year,-1,getdate()),'yyyy'),'Q2','NULL')))))) AS Quarter
FROM BATCHDETAIL INNER JOIN 
(SELECT  Min(BATCHDETAIL.DATEOFPAYMENT) AS FirstPaid, BATCHDETAIL.SERIALNUMBER
FROM BATCHDETAIL
GROUP BY BATCHDETAIL.SERIALNUMBER) SO
 ON BATCHDETAIL.SERIALNUMBER = SO.SERIALNUMBER
WHERE (((BATCHDETAIL.PAYMENTTYPE)='Cash'))
GROUP BY IIf(datepart(month,[FirstPaid])>7 And datepart(month,[FirstPaid]) In (7,8,9) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q1',
IIf(datepart(month,[FirstPaid])>7 And datepart(month,[FirstPaid]) In (10,11,12) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q2',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (1,2,3) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q3',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (4,5,6) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q4',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (7,8,9) And datepart(year,[FirstPaid])=datepart(year,DateAdd(year,-1,getdate())),'Q1',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (10,11,12) And datepart(year,[FirstPaid])=datepart(year,DateAdd(year,-1,getdate())),'Q2','NULL'))))))
HAVING 
(((IIf(datepart(month,[FirstPaid])>7 And datepart(month,[FirstPaid]) In (7,8,9) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q1',
IIf(datepart(month,[FirstPaid])>7 And datepart(month,[FirstPaid]) In (10,11,12) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q2',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (1,2,3) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q3',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (4,5,6) And datepart(year,[FirstPaid])=datepart(year,Getdate()),'Q4',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (7,8,9) And datepart(year,[FirstPaid])=datepart(year,DateAdd(year,-1,getdate())),'Q1',
IIf(datepart(month,[FirstPaid])<7 And datepart(month,[FirstPaid]) In (10,11,12) And datepart(year,[FirstPaid])=datepart(year,DateAdd(year,-1,getdate())),'Q2','NULL')))))))<>'Null'));

如果我想根据派生的季度进行分组,则使用第一个日期将付款作为FirstPaid过帐以获得IIF条件下的季度。我被困在试图获得分组而没有在Group中的FirstPaid字段包括废弃季度分组,任何帮助感激地收到。这是在SQL Server 2012中

阿德里安

2 个答案:

答案 0 :(得分:0)

您似乎正在尝试在T-SQL中编写自定义日历代码。如果不回答这个问题,请查看我在SQL Calendar Table上的文章,这是一个关于如何创建可以处理此问题的表的演示和可下载代码。

可以在代码中更改您定义的季度分组以满足您的需求。

答案 1 :(得分:0)

如果你想在7-1-2014之后按季度计算所有内容,按季度分组可能对你有用

SELECT 
    COUNT(*) AS CountOfSERIALNUMBER,
    CASE WHEN FirstPaidMonth IN (7,8,9) THEN 'Q1'
         WHEN FirstPaidMonth IN (10,11,12) THEN 'Q2'
         WHEN FirstPaidMonth IN (1,2,3) THEN 'Q3'
         ELSE 'Q4' END AS Quarter
FROM
(
    SELECT
        DATEPART(MONTH,MIN(BATCHDETAIL.DATEOFPAYMENT)) AS FirstPaidMonth,
        BATCHDETAIL.SERIALNUMBER
    FROM
        BATCHDETAIL
    WHERE
        BATCHDETAIL.PAYMENTTYPE = 'Cash'
    GROUP BY
        BATCHDETAIL.SERIALNUMBER
    HAVING 
        MIN(BATCHDETAIL.DATEOFPAYMENT) >= 
            CASE WHEN DATEPART(MONTH, GETDATE()) >= 7 
                THEN DATETIMEFROMPARTS(DATEPART(YEAR, GETDATE()), 7, 1,0,0,0,0) 
                ELSE DATETIMEFROMPARTS(DATEPART(YEAR, GETDATE()) - 1, 7, 1,0,0,0,0)
            END
) t
GROUP BY CASE WHEN FirstPaidMonth IN (7,8,9) THEN 'Q1'
         WHEN FirstPaidMonth IN (10,11,12) THEN 'Q2'
         WHEN FirstPaidMonth IN (1,2,3) THEN 'Q3'
         ELSE 'Q4' END

您还可以创建一个CTE,其中包含您要查找的日期及其各自的季度,然后加入该计划。

;WITH cte (BeginDate, EndDate, [Quarter])
AS (
  SELECT '2014-07-01', '2014-10-01', 'Q1' UNION ALL
  SELECT '2014-10-01', '2015-01-01', 'Q2' UNION ALL
  SELECT '2015-01-01', '2015-04-01', 'Q3' UNION ALL
  SELECT '2015-04-01', '2015-07-01', 'Q4' UNION ALL
  SELECT '2015-07-01', '2015-10-01', 'Q1' UNION ALL
  SELECT '2015-10-01', '2016-01-01', 'Q2' 
)  
SELECT 
    COUNT(*) AS CountOfSERIALNUMBER,
    [Quarter]
FROM
(
    SELECT
        cte.[Quarter],
        bd.SERIALNUMBER,
        ROW_NUMBER() OVER (PARTITION BY bd.SERIALNUMBER ORDER BY bd.DATEOFPAYMENT) RN
    FROM
        BATCHDETAIL bd
        JOIN cte ON bd.DATEOFPAYMENT >= cte.BeginDate AND bd.DATEOFPAYMENT < cte.EndDate
    WHERE
        bd.PAYMENTTYPE = 'Cash'
    GROUP BY
        cte.[Quarter],  
        bd.SERIALNUMBER,
        bd.DATEOFPAYMENT
    HAVING 
        MIN(bd.DATEOFPAYMENT) >= '07/01/2014'
) t
WHERE t.RN = 1
GROUP BY [Quarter]