T-SQL - 按周调整

时间:2012-03-26 12:29:10

标签: sql sql-server sql-server-2008 tsql pivot

我目前正在尝试创建一个T-SQL,它运行一个表中的交付列表,并按客户和仓库对它们进行分组 - 所以每一行都是

客户,仓库,总价值(称为费率的列的总和)

但是,客户希望将“总价值”拆分为过去9周 - 而不是总价值,我们会有这样的列:

22/01/2012  29/01/2012  05/02/2012  12/02/2012  19/02/2012  26/02/2012  04/03/2012  11/03/2012  18/03/2012

当他们运行查询时,日期当然会发生变化 - 这只是过去9周。他们还想要一个列所有这些的平均值。

我理解枢轴可能对我有所帮助,但我对如何做到这一点感到有些困惑。这是我当前的查询:

SELECT d.Name AS 'Depot, s.Name AS 'Customer', SUM(c.Rates) AS 'Total Value'
FROM Deliveries AS c INNER JOIN Account AS s ON c.Customer = s.ID
INNER JOIN Depots AS d ON c.CollectionDepot = d.Letter
GROUP BY d.Name, s.Name

非常感谢!

编辑:这是当前数据的屏幕截图 - 我们最后不需要“总计”列,只是为了向您展示。 “日期”列出现在“交货”表中,称为“TripDate”

enter image description here

2 个答案:

答案 0 :(得分:3)

您必须使用您的SQL Server版本中提供的PIVOT关键字。我已经概述了您的查询应该如何看待,当然需要进行一些调整,因为如果没有您的数据副本就很难进行测试。

  SELECT Depots.Name AS 'Depot',  Account.Name, '22/01/2012',  '29/01/2012',  '05/02/2012',  '12/02/2012',
   FROM 
(SELECT Name, 
    FROM Deliveries
    INNER JOIN Account ON Deliveries.Customer = Account.ID
    INNER JOIN Depots ON Account.CollectionDepot) AS Source
PIVOT
(
    SUM(Deliveries.Rates)
    FOR Date IN ('22/01/2012',  '29/01/2012',  '05/02/2012',  '12/02/2012')
) AS 'Pivot Table'

供参考,您可以将其作为指南:

http://msdn.microsoft.com/en-us/library/ms177410.aspx

答案 1 :(得分:3)

不知道您的确切数据。很难预测你得到了什么。但我可以给你一个解决方案的建议。

表格结构

CREATE TABLE Deliveries
(
    Customer INT,
    CollectionDepot INT,
    Rates FLOAT,
    TripDate DATETIME
)
CREATE TABLE Account
(
    Name VARCHAR(100),
    ID INT
)
CREATE TABLE Depots
(
    Name VARCHAR(100),
    Letter INT
)

测试数据

INSERT INTO Deliveries
VALUES
    (1,1,452,GETDATE()-10),
    (1,1,800,GETDATE()-30),
    (1,1,7895,GETDATE()-2),
    (1,1,451,GETDATE()-2),
    (1,1,478,GETDATE()-89),
    (1,1,4512,GETDATE()-31),
    (1,1,782,GETDATE()-20),
    (1,1,652,GETDATE()-5),
    (1,1,752,GETDATE()-452)

INSERT INTO Account
VALUES
    ('Customer 1',1)

INSERT INTO Depots
VALUES
    ('Depot 1',1)

包含范围和格式化日期的表格

CREATE TABLE #tmp
(
    StartDate DATETIME,
    EndDate DATETIME,
    FomatedDate VARCHAR(20)
)

计算日期范围

;WITH Nbrs ( n ) AS (
        SELECT 0 UNION ALL
        SELECT 1+n FROM Nbrs WHERE n < 8 )
INSERT INTO #tmp
SELECT
    DATEADD(WEEK,-n-1,GETDATE()),
    DATEADD(WEEK,-n,GETDATE()),
    convert(varchar, DATEADD(WEEK,-n,GETDATE()), 112)
FROM
    Nbrs
ORDER BY
    -n

数据透视表的日期列

DECLARE @cols VARCHAR(MAX)
SELECT  @cols = COALESCE(@cols + ','+QUOTENAME(FomatedDate),
                     QUOTENAME(FomatedDate))
FROM 
    #tmp

声明一些动态sql并执行它

DECLARE @query NVARCHAR(4000)=
N'SELECT
    *
FROM
(
    SELECT 
        Depots.Name AS Depot, 
        Account.Name AS Customer, 
        Deliveries.Rates,
        tmp.FomatedDate,
        AVG(Deliveries.Rates) OVER(PARTITION BY 1) AS Average,
        SUM(Deliveries.Rates) OVER(PARTITION BY 1) AS Total
    FROM 
        Deliveries
        JOIN Account 
            ON Deliveries.Customer = Account.ID
        JOIN Depots
            ON Deliveries.CollectionDepot = Depots.Letter
        JOIN #tmp AS tmp
            ON Deliveries.TripDate BETWEEN tmp.StartDate AND tmp.EndDate
) AS p
PIVOT
(
    AVG(rates)
    FOR FomatedDate IN ('+@cols+')
) AS pvt'

EXECUTE(@query)

然后自己清理。

DROP TABLE Deliveries
DROP TABLE Account
DROP TABLE Depots
DROP TABLE #tmp