带有多个小计的SQL查询

时间:2014-09-05 14:33:45

标签: sql sql-server sql-server-2008

希望有人可以帮助我。

我试图在sql查询中使用小计,但不是另一列。

查看截图,其中包含我得到的结果和解释

Screenshot

这是我到目前为止的查询

SELECT 
    ar.Person_Id AS 'Id', 
    pa.Serial_Number, 
    ar.Family_Name + ', '+ar.First_Name AS 'Name', 
    CASE WHEN ar.Line_Type = 'A' THEN 'Activity: '+ar.Item_Name ELSE 'Hotel: '+ar.Item_Name END AS 'Description', 
    CAST(IsNull(ar.Old_Amount_Excl_VAT,0) AS DECIMAL(10,2)) AS 'Amount Excl VAT', 
    CAST(IsNull(ar.Old_Amount_Incl_VAT,0) AS DECIMAL(10,2)) AS 'Amount Incl VAT', 
    CAST(IsNull(ar.Old_Amount_Incl_VAT,0) - IsNull(ar.Old_Amount_Excl_VAT,0) AS DECIMAL(10,2)) AS 'VAT Amount', 
    p.Currency_Code, 
    ( 
    SELECT TOP 1 pt.Payment_Type + ' ' + pt.Description AS Payment_Type FROM PaymentsPerPerson ppp 
    LEFT OUTER JOIN PaymentCodes pc ON ppp.Client_Id = pc.Client_Id AND ppp.Project_Id = pc.Project_Id AND ppp.Payment_Code = pc.Payment_Code 
    LEFT OUTER JOIN PaymentTypes pt ON ppp.Client_Id = pt.Client_Id AND ppp.Project_Id = pt.Project_Id AND pt.Payment_Type = pc.Payment_Type  
    WHERE ppp.Client_Id = ar.Client_Id AND  ppp.Project_Id = ar.Project_Id AND  ppp.Person_Id = ar.Person_Id AND  ppp.Line_Number IN (SELECT MAX(Line_Number) FROM PaymentsPerPerson WHERE Person_Id = ar.Person_Id) ) AS Payment_Type, 
    ( 
    SELECT TOP 1 convert(varchar, Payment_Date, 120) AS Payment_Date FROM PaymentsPerPerson  WHERE Client_Id = ar.Client_Id AND Project_Id = ar.Project_Id AND Person_Id = ar.Person_Id ORDER BY Line_Number DESC 
    ) AS Payment_Date, 
    ( 
    SELECT TOP 1 Card_Reference FROM PaymentsPerPerson  WHERE Client_Id = ar.Client_Id AND Project_Id = ar.Project_Id AND Person_Id = ar.Person_Id ORDER BY Line_Number DESC 
    ) AS Transaction_Id, 
    convert(varchar, getdate(), 120) AS Date 
FROM 
    AccountingReport ar 
LEFT OUTER JOIN Participants pa ON ar.Client_Id = pa.Client_Id AND ar.Project_Id = pa.Project_Id AND ar.Person_Id = pa.Person_Id AND pa.Date_Registered IS NOT NULL 
LEFT OUTER JOIN Projects p ON ar.Client_Id = p.Client_Id AND ar.Project_Id = p.Project_Id 
RIGHT OUTER JOIN PaymentsPerPerson ppp ON ar.Client_Id = ppp.Client_Id AND ar.Project_Id = ppp.Project_Id AND ar.Person_Id = ppp.Person_Id 
WHERE 
    ar.Client_Id = 'CLIENTID' AND 
    ar.Project_Id = 'PROJECTID' AND 
    (IsNull(Old_Amount_Excl_VAT,0) <> 0 
    OR IsNull(Old_Amount_Incl_VAT,0) <> 0) 
    AND pa.Date_Registered IS NOT NULL 
ORDER BY 
    ar.Person_Id, 
    Item_Id, 
    SubItem_Id, 
    SubSubItem_Id 

我尝试过使用ROLLUP,但这就是我得到的

Screenshot 2

这是我使用汇总

时使用的查询
SELECT 
    CASE WHEN (GROUPING(ar.Person_Id) = 1) THEN 0
            ELSE ISNULL(ar.Person_Id, 'UNKNOWN')
    END AS 'Id',
    CASE WHEN (GROUPING(pa.Serial_Number) = 1) THEN 0
            ELSE ISNULL(pa.Serial_Number, 'UNKNOWN')
    END AS Serial_Number,
    CASE WHEN (GROUPING(ar.Family_Name + ', '+ar.First_Name) = 1) THEN 'ALL'
            ELSE ISNULL(ar.Family_Name + ', '+ar.First_Name, 'UNKNOWN')
    END AS 'Name',
    CASE WHEN ar.Line_Type = 'A' THEN 'Activity: '+ar.Item_Name ELSE 'Hotel: '+ar.Item_Name END AS 'Description',
    SUM(CAST(IsNull(ar.Old_Amount_Excl_VAT,0) AS DECIMAL(10,2))) AS 'Amount Excl VAT', 
    SUM(CAST(IsNull(ar.Old_Amount_Incl_VAT,0) AS DECIMAL(10,2))) AS 'Amount Incl VAT', 
    SUM(CAST(IsNull(ar.Old_Amount_Incl_VAT,0) - IsNull(ar.Old_Amount_Excl_VAT,0) AS DECIMAL(10,2))) AS 'VAT Amount', 
    CASE WHEN (GROUPING(p.Currency_Code) = 1) THEN 'ALL'
            ELSE ISNULL(p.Currency_Code, 'UNKNOWN')
    END AS Currency_Code,
    ( 
        SELECT TOP 1 pt.Payment_Type + ' ' + pt.Description AS Payment_Type FROM PaymentsPerPerson ppp 
        LEFT OUTER JOIN PaymentCodes pc ON ppp.Client_Id = pc.Client_Id AND ppp.Project_Id = pc.Project_Id AND ppp.Payment_Code = pc.Payment_Code 
        LEFT OUTER JOIN PaymentTypes pt ON ppp.Client_Id = pt.Client_Id AND ppp.Project_Id = pt.Project_Id AND pt.Payment_Type = pc.Payment_Type  
        WHERE ppp.Client_Id = ar.Client_Id AND  ppp.Project_Id = ar.Project_Id AND  ppp.Person_Id = ar.Person_Id AND  ppp.Line_Number IN (SELECT MAX(Line_Number) FROM PaymentsPerPerson WHERE Person_Id = ar.Person_Id) 
    ) AS Payment_Type, 
    ( 
        SELECT TOP 1 convert(varchar, Payment_Date, 120) AS Payment_Date FROM PaymentsPerPerson  WHERE Client_Id = ar.Client_Id AND Project_Id = ar.Project_Id AND Person_Id = ar.Person_Id ORDER BY Line_Number DESC 
    ) AS Payment_Date, 
    ( 
        SELECT TOP 1 Card_Reference FROM PaymentsPerPerson  WHERE Client_Id = ar.Client_Id AND Project_Id = ar.Project_Id AND Person_Id = ar.Person_Id ORDER BY Line_Number DESC 
    ) AS Transaction_Id, 
    CONVERT(varchar, GETDATE(), 120) AS Date
FROM 
    AccountingReport ar 
LEFT OUTER JOIN Participants pa ON ar.Client_Id = pa.Client_Id AND ar.Project_Id = pa.Project_Id AND ar.Person_Id = pa.Person_Id AND pa.Date_Registered IS NOT NULL 
LEFT OUTER JOIN Projects p ON ar.Client_Id = p.Client_Id AND ar.Project_Id = p.Project_Id 
RIGHT OUTER JOIN PaymentsPerPerson ppp ON ar.Client_Id = ppp.Client_Id AND ar.Project_Id = ppp.Project_Id AND ar.Person_Id = ppp.Person_Id 
WHERE 
    ar.Client_Id = 'CLIENTID' AND 
    ar.Project_Id = 'PROJECTID' AND 
    (IsNull(Old_Amount_Excl_VAT,0) <> 0 
    OR IsNull(Old_Amount_Incl_VAT,0) <> 0) 
    AND pa.Date_Registered IS NOT NULL 
GROUP BY 
    ar.Client_Id,
    ar.Project_Id,
    ar.Person_Id,
    pa.Serial_Number,
    ar.Line_Type, ar.Item_Name, ar.Item_Id, ar.SubItem_Id, ar.SubSubItem_Id,
    p.Currency_Code,
    ar.Family_Name + ', '+ar.First_Name WITH ROLLUP
ORDER BY 
    ar.Person_Id, 
    Item_Id, 
    SubItem_Id, 
    SubSubItem_Id 

任何想法都会很棒,因为我不是SQL专家。

是否可以使用SQL Server?或者我需要一些脚本(asp,php)来生成它?

如果可以使用SQL查询完成它会更好,因为当客户端点击按钮时,我们会将结果导出为Excel Reports。

4 个答案:

答案 0 :(得分:2)

如果您要导出到Excel,我认为您最好的选择是从第一个查询中导出,并在Excel中使用小计(在“数据”菜单下)。您可以通过Excel中的宏或应用程序代码(点击&#34;导出&#34;按钮)自动执行此操作。

答案 1 :(得分:1)

WITH
DataSet AS (
--Your original query. For simplicity, I hard-coded the results.
    SELECT  '4142722'AS ID, 1 AS Serial_Number, 'Name1' AS Name, 'Activity: Description' AS DESCRIPTION, 10000.00 AS AmountExclVAT,10000.00 AS AmountInclVAT, 0 AS VATAmount, 'EUR' AS Currency_Code, NULL AS Payment_Type, NULL AS Payment_Date, NULL AS Trasaction_ID, NULL as Date
    UNION
    SELECT  '4142722'AS ID, 1 AS Serial_Number, 'Name1' AS Name, 'Activity: Description1' AS DESCRIPTION, 2000.00 AS AmountExclVAT,2000.00 AS AmountInclVAT, 0 AS VATAmount, 'EUR' AS Currency_Code, NULL AS Payment_Type, NULL AS Payment_Date, NULL AS Trasaction_ID, NULL as Date
    UNION
    SELECT  '4142722'AS ID, 1 AS Serial_Number, 'Name1' AS Name, 'Activity: Description' AS DESCRIPTION, -1000.00 AS AmountExclVAT,-1000.00 AS AmountInclVAT, 0 AS VATAmount, 'EUR' AS Currency_Code, NULL AS Payment_Type, NULL AS Payment_Date, NULL AS Trasaction_ID, NULL as Date
    UNION
    SELECT  '4142724'AS ID, 3 AS Serial_Number, 'Name2' AS Name, 'Activity: Description' AS DESCRIPTION, 5000.00 AS AmountExclVAT,5000.00 AS AmountInclVAT, 0 AS VATAmount, 'EUR' AS Currency_Code, NULL AS Payment_Type, NULL AS Payment_Date, NULL AS Trasaction_ID, NULL as Date
    UNION
    SELECT  '4142724'AS ID, 3 AS Serial_Number, 'Name2' AS Name, 'Activity: Description' AS DESCRIPTION, 2000.00 AS AmountExclVAT,2000.00 AS AmountInclVAT, 0 AS VATAmount, 'EUR' AS Currency_Code, NULL AS Payment_Type, NULL AS Payment_Date, NULL AS Trasaction_ID, NULL as Date
)
,
SubTotals AS (
    SELECT
         ID
        ,NULL AS SERIAL_NUMBER
        ,NULL AS NAME
        ,'Subtotal' DESCRIPTION
        ,SUM(AmountExclVAT) sum_AmountExclVAT
        ,SUM(AmountInclVAT) sum_AmountInclVAT
        ,SUM(VATAmount) sum_VATAmount
        ,NULL AS CurrencyCode
        ,NULL AS Payment_Type
        ,NULL AS Payment_Date
        ,NULL AS Trasaction_ID
        ,NULL as Date
    FROM
        DataSet
    GROUP BY
         ID
        ,SERIAL_NUMBER
        ,NAME
)   
SELECT * FROM DataSet
UNION
SELECT * FROM SubTotals
ORDER BY ID, DESCRIPTION

答案 2 :(得分:0)

如果person_id针对某个人,那么我们不需要在汇总中使用person_id列,如果我们将汇总更改为立方体,我们将获得所有特定人名称的输出好。请试一试。

答案 3 :(得分:0)

弗雷德里科, 我使用WITH语句(该NEEDS之前的SQL语句以分号结束)创建了一个公用表表达式,并添加了一个单独的UNION ALL部件,该部件使用GROUP BY并创建小计。我无法完全测试它,因为我没有得到表定义,并且查询中缺少一些ORDER BY列名,但是它是:

;

WITH Amounts (Id, Serial_Number, Name, Description, [Amount Excl VAT], [Amount Incl VAT], [VAT Amount], Currency_Code, Payment_type, Payment_Date, Transaction_Id, [Date] )
  AS (
  SELECT 
    ar.Person_Id AS 'Id', 
    pa.Serial_Number, 
    ar.Family_Name + ', '+ar.First_Name AS 'Name', 
    CASE WHEN ar.Line_Type = 'A' THEN 'Activity: '+ar.Item_Name ELSE 'Hotel: '+ar.Item_Name END AS 'Description', 
    CAST(IsNull(ar.Old_Amount_Excl_VAT,0) AS DECIMAL(10,2)) AS 'Amount Excl VAT', 
    CAST(IsNull(ar.Old_Amount_Incl_VAT,0) AS DECIMAL(10,2)) AS 'Amount Incl VAT', 
    CAST(IsNull(ar.Old_Amount_Incl_VAT,0) - IsNull(ar.Old_Amount_Excl_VAT,0) AS DECIMAL(10,2)) AS 'VAT Amount', 
    p.Currency_Code, 
    ( 
    SELECT TOP 1 pt.Payment_Type + ' ' + pt.Description AS Payment_Type FROM PaymentsPerPerson ppp 
    LEFT OUTER JOIN PaymentCodes pc ON ppp.Client_Id = pc.Client_Id AND ppp.Project_Id = pc.Project_Id AND ppp.Payment_Code = pc.Payment_Code 
    LEFT OUTER JOIN PaymentTypes pt ON ppp.Client_Id = pt.Client_Id AND ppp.Project_Id = pt.Project_Id AND pt.Payment_Type = pc.Payment_Type  
    WHERE ppp.Client_Id = ar.Client_Id AND  ppp.Project_Id = ar.Project_Id AND  ppp.Person_Id = ar.Person_Id AND  ppp.Line_Number IN (SELECT MAX(Line_Number) FROM PaymentsPerPerson WHERE Person_Id = ar.Person_Id) ) AS Payment_Type, 
    ( 
    SELECT TOP 1 convert(varchar, Payment_Date, 120) AS Payment_Date FROM PaymentsPerPerson  WHERE Client_Id = ar.Client_Id AND Project_Id = ar.Project_Id AND Person_Id = ar.Person_Id ORDER BY Line_Number DESC 
    ) AS Payment_Date, 
    ( 
    SELECT TOP 1 Card_Reference FROM PaymentsPerPerson  WHERE Client_Id = ar.Client_Id AND Project_Id = ar.Project_Id AND Person_Id = ar.Person_Id ORDER BY Line_Number DESC 
    ) AS Transaction_Id, 
    convert(varchar, getdate(), 120) AS Date 
FROM 
    AccountingReport ar 
LEFT OUTER JOIN Participants pa ON ar.Client_Id = pa.Client_Id AND ar.Project_Id = pa.Project_Id AND ar.Person_Id = pa.Person_Id AND pa.Date_Registered IS NOT NULL 
LEFT OUTER JOIN Projects p ON ar.Client_Id = p.Client_Id AND ar.Project_Id = p.Project_Id 
RIGHT OUTER JOIN PaymentsPerPerson ppp ON ar.Client_Id = ppp.Client_Id AND ar.Project_Id = ppp.Project_Id AND ar.Person_Id = ppp.Person_Id 
WHERE 
    ar.Client_Id = 'CLIENTID' AND 
    ar.Project_Id = 'PROJECTID' AND 
    (IsNull(Old_Amount_Excl_VAT,0) <> 0 
    OR IsNull(Old_Amount_Incl_VAT,0) <> 0) 
    AND pa.Date_Registered IS NOT NULL 
)
SELECT Id, 1 AS Level, Serial_Number, Name, Description,
    [Amount Excl VAT],
    [Amount Incl VAT],
    [VAT Amount],
    Currency_Code, Payment_type, Payment_Date, Transaction_Id, [Date]
FROM Amounts
UNION ALL
SELECT Id, 2 AS Level, Serial_Number, Name, Description,
    SUM( [Amount Excl VAT] ) AS [Amount Excl VAT],  
    SUM( [Amount Incl VAT] ) AS [Amount Incl VAT], 
    SUM( [VAT Amount] ) AS [VAT Amount],
    Currency_code, Payment_type, Payment_Date, Transaction_Id, [Date]
    FROM Amounts
    GROUP BY Id, Serial_Number, Name, Description, currency_code, Payment_type, Payment_Date, Transaction_Id, [Date]
ORDER BY 
    Id, 
    Level,
    Item_Id, 
    SubItem_Id, 
    SubSubItem_Id