SQL帮助 - 按州销售(SAP Business One)

时间:2014-04-22 13:39:55

标签: sql sql-server sap

想知道是否有人可以帮我查询我试图用来从我的数据库中提取销售信息的查询。我正在尝试建立一份报告,以显示各州的所有销售情况。我遇到过这段代码,虽然它接近我需要的东西,但并不是全部。

随着每个州的销售,我需要包括库存销售的仓库(T1。[WhsCode])。我还需要对每一列进行求和(我知道您可以按Ctrl和Click来获取每列底部的总计,但希望它们自动出现在最终报告中)。有人可以帮忙吗?

以下是目前的查询:

SELECT  T0.State1 AS 'Bill-to State',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 1 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'JAN Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 2 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'FEB Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 3 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'MAR Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 4 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'APR Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 5 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'MAY Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 6 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'JUN Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 7 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'JUL Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 8 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'AUG Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 9 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'SEP Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 10 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'OCT Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 11 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'NOV Amt',
        (
          SELECT    SUM(T1.DocTotal)
          FROM      OINV T1 WITH ( NOLOCK )
          INNER JOIN OCRD T2 ON T2.CardCode = T1.CardCode
          WHERE     MONTH(T1.DOCDATE) = 12 AND
                    T2.State1 = T0.State1 AND
                    YEAR(T1.DOCDATE) = YEAR(GETDATE())
        ) AS 'DEC Amt'
FROM    dbo.OCRD T0
LEFT JOIN dbo.OINV T1 ON T1.CardCode = T0.CardCode
GROUP BY T0.State1
ORDER BY T0.State1

2 个答案:

答案 0 :(得分:0)

而是使用SQL Pivot:

-- Pivot table with one row and five columns
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days, 
[0], [1], [2], [3], [4]
FROM
(SELECT DaysToManufacture, StandardCost 
    FROM Production.Product) AS SourceTable
PIVOT
(
AVG(StandardCost)
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])
) AS PivotTable;

答案 1 :(得分:0)

您可以使用条件聚合:

SELECT  [Bill-To-State] =  ISNULL(T0.State1, 'Total'),
        Warehouse = T1.[WhsCode],
        [Jan Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 1 THEN T1.DocTotal ELSE 0 END),
        [Feb Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 2 THEN T1.DocTotal ELSE 0 END),
        [Mar Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 3 THEN T1.DocTotal ELSE 0 END),
        [Apr Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 4 THEN T1.DocTotal ELSE 0 END),
        [May Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 5 THEN T1.DocTotal ELSE 0 END),
        [Jun Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 6 THEN T1.DocTotal ELSE 0 END),
        [Jul Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 7 THEN T1.DocTotal ELSE 0 END),
        [Aug Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 8 THEN T1.DocTotal ELSE 0 END),
        [Sep Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 9 THEN T1.DocTotal ELSE 0 END),
        [Oct Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 10 THEN T1.DocTotal ELSE 0 END),
        [Nov Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 11 THEN T1.DocTotal ELSE 0 END),
        [Dec Amt] = SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 12 THEN T1.DocTotal ELSE 0 END)
FROM    dbo.OCRD T0
        LEFT JOIN dbo.OINV T1 
            ON T1.CardCode = T0.CardCode
WHERE   T1.DocDate >= DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)
AND     T1.DocDate < DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()) + 1, 0)
GROUP BY GROUPING SETS ((T0.State1, T1.[WhsCode]), ());

N.B我已使用我首选的Alias = Expression方法移除了deprecated literals for aliases。我更喜欢这个,因为我发现能够更容易地看到立即调用列,而不是必须向右扫描才能找到列的结尾。这完全是个人偏好,如果您对expression AS Alias更熟悉,那么您应该使用以下内容,因为它仍然避免使用文字。

SELECT  ISNULL(T0.State1, 'Total') AS [Bill-To-State],
        T1.[WhsCode] AS Warehouse,
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 1 THEN T1.DocTotal ELSE 0 END) AS [Jan Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 2 THEN T1.DocTotal ELSE 0 END) AS [Feb Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 3 THEN T1.DocTotal ELSE 0 END) AS [Mar Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 4 THEN T1.DocTotal ELSE 0 END) AS [Apr Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 5 THEN T1.DocTotal ELSE 0 END) AS [May Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 6 THEN T1.DocTotal ELSE 0 END) AS [Jun Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 7 THEN T1.DocTotal ELSE 0 END) AS [Jul Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 8 THEN T1.DocTotal ELSE 0 END) AS [Aug Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 9 THEN T1.DocTotal ELSE 0 END) AS [Sep Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 10 THEN T1.DocTotal ELSE 0 END) AS [Oct Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 11 THEN T1.DocTotal ELSE 0 END) AS [Nov Amt],
        SUM(CASE WHEN DATEPART(MONTH, T1.DocDate) = 12 THEN T1.DocTotal ELSE 0 END) AS [Dec Amt]
FROM    dbo.OCRD T0
        LEFT JOIN dbo.OINV T1 
            ON T1.CardCode = T0.CardCode
WHERE   T1.DocDate >= DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)
AND     T1.DocDate < DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()) + 1, 0)
GROUP BY GROUPING SETS ((T0.State1, T1.[WhsCode]), ());

另请注意,我已更换

WHERE YEAR(T1.DocDate) = YEAR(GETDATE())

WHERE   T1.DocDate >= DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)
AND     T1.DocDate < DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()) + 1, 0)

这可能看起来很长,但它会允许优化器使用t1.DocDate上的任何索引,因为不必在每一行都执行YEAR函数。

另一件事是

的使用
GROUP BY GROUPING SETS ((T0.State1, T1.[WhsCode]), ());

这将添加您的总行数,您必须有两个结果集,一个按“(T0.State1, T1.[WhsCode])”分组,一个分组为“()”。在此总行中,T0.State1T1.[WhsCode]都将为空,因此我使用ISNULL(T0.State1, 'Total')使其在此行中显示总计。