1

我是 T-SQL 的新手,需要帮助将 Excel 报告转换为 SQL 上的运行。我有一个 SQL 表,记录了每个库房的所有日常库存交易(进/出)。我需要创建一个报告,列出每个位置每个产品的当前库存水平和每个位置的数量,如下所示。换句话说,每个地方的当前库存水平。

我还需要有关如何将首选输出报告(如下)作为视图插入 SQL Server 的帮助,以便我可以每个月一遍又一遍地运行它。

提前致谢!

库存日志表:

PubID   QTY LocationID  Transaction
1       10  1           Add
1       20  2           Add
1       30  3           Add
1       5   1           Sold
1       10  2           Sold
1       5   3           Sold
2       10  1           Add
2       10  2           Add
2       5   2           Sold
2       8   2           Sold
1       20  1           Add
1       20  2           Add
2       2   2           Sold

首选输出表:

PubID   Local_1 Local_2 Local_3 Total
1       25      30      25      80
2       5       0       0       5
Total   30      30      25      85

我在这里看到了很多相近的例子,但大多数只是添加价值,而我需要从已添加库存中减去已售库存以获得我在每一列中的总数。

右侧和底部的行总计和列总计是加号,但如果没有它更容易,则不需要。

谢谢!

4

3 回答 3

1
于 2014-03-04T20:04:40.530 回答
0

下面的查询可以满足您的需要。我可能有一个额外的组可以合并为 1,但你明白了。

DECLARE  @InventoryLog TABLE
(
    PubId INT,
    Qty INT,
    LocationId INT,
    [Transaction] Varchar(4)

)

DECLARE  @LocationTable TABLE
(
    Id INT,
    Name VarChar(10)

)

INSERT INTO @LocationTable
VALUES
(1, 'LOC_1'),
(2, 'LOC_2'),
(3, 'LOC_3')

INSERT INTO @InventoryLog
VALUES 
(1 ,      10,  1 ,          'Add'),
(1 ,      20,  2 ,          'Add'),
(1 ,      30,  3 ,          'Add'),
(1 ,      5 ,  1 ,          'Sold'),
(1 ,      10,  2 ,          'Sold'),
(1 ,      5 ,  3 ,          'Sold'),
(2 ,      10,  1 ,          'Add'),
(2 ,      10,  2 ,          'Add'),
(2 ,      5 ,  2 ,          'Sold'),
(2 ,      8 ,  2 ,          'Sold'),
(1 ,      20,  1 ,          'Add'),
(1 ,      20,  2 ,          'Add'),
(2 ,      2 ,  2 ,          'Sold')

SELECT PubId, 
       lT.Name LocationName, 
       CASE
            WHEN [Transaction] ='Add' Then Qty
            WHEN [Transaction] ='Sold' Then -Qty
       END as Quantity
INTO   #TempInventoryTable
FROM @InventoryLog iL
INNER JOIN @LocationTable  lT on iL.LocationId = lT.Id

SELECT * INTO #AlmostThere
FROM
(
SELECT PubId, 
       ISNULL(LOC_1,0) LOC_1,
       ISNULL(LOC_2,0) LOC_2, 
       ISNULL(LOC_3,0) LOC_3,
       SUM(ISNULL(LOC_1,0) + ISNULL(LOC_2,0) + ISNULL(LOC_3,0)) AS TOTAL
FROM #TempInventoryTable s
PIVOT 
(
    SUM(Quantity)
    FOR LocationName in (LOC_1,LOC_2,LOC_3)
) as b
GROUP BY PubId, LOC_1, LOC_2, LOC_3
) b

SELECT CAST(PubId as VARCHAR(10))PubId,
       LOC_1,
       LOC_2,
       LOC_3,
       TOTAL
FROM #AlmostThere
UNION
SELECT ISNULL(CAST(PubId AS VARCHAR(10)),'TOTAL')  PubId, 
       [LOC_1]= SUM(LOC_1),
       [LOC_2]= SUM(LOC_2),
       [LOC_3]= SUM(LOC_3),
       [TOTAL]= SUM(TOTAL)
FROM #AlmostThere
GROUP BY ROLLUP(PubId)




DROP TABLE #TempInventoryTable
DROP TABLE #AlmostThere



 PubId  LOC_1   LOC_2   LOC_3   TOTAL 

   1     25  30  25  80 

   2     10  -5   0   5

 TOTAL   35  25  25  85

Sql 小提琴

于 2014-02-28T13:40:14.890 回答
0

这是另一种方法:在透视之前聚合数据,然后透视聚合结果。

与我的其他建议相比,这种方法在语法上要简单得多,这也可能使其更易于理解和维护。

所有的聚合都是在CUBE()分组功能的帮助下完成的。基本查询是这样的:

SELECT
  PubID,
  LocationID,
  QTY = SUM(CASE [Transaction] WHEN 'Add' THEN QTY ELSE -QTY END)
FROM dbo.InventoryLog
GROUP BY CUBE(PubID, LocationID)

您可以看到与我的其他答案相同的 CASE 表达式,只是这次可以直接用作 SUM 的参数。

使用 CUBE 的聚合不仅可以得到总计(PubID, LocationID),还可以分别得到总计,PubID以及LocationID总计。这是您问题中示例的查询结果:

PubID  LocationID  QTY
-----  ----------  ---
1      1           35
2      1           10
NULL   1           45
1      2           50
2      2           25
NULL   2           75
1      3           35
NULL   3           35
NULL   NULL        155
1      NULL        120
2      NULL        35

带有 NULLLocationID的行是最终结果集中的行总计,带有 NULL 的行PubID是列总计。两列中都有 NULL 的行是总计。

在继续进行透视之前,我们需要为透视结果准备列名。如果名称应该从 的值派生LocationID,则以下声明将替换LocationID原始查询的 SELECT 子句:

Location = COALESCE('Local_' + CAST(LocationID AS varchar(10)), 'Total')

我们还可以在同一阶段替换'Total'NULL PubID,因此这将PubID在 SELECT 子句中替换:

PubID = COALESCE(CAST(PubID AS varchar(10)), 'Total')

现在结果将如下所示:

PubID  LocationID  QTY
-----  ----------  ---
1      Local_1     35
2      Local_1     10
Total  Local_1     45
1      Local_2     50
2      Local_2     25
Total  Local_2     75
1      Local_3     35
Total  Local_3     35
Total  Total       155
1      Total       120
2      Total       35

至此,一切都已准备好应用 PIVOT。此查询根据所需格式转换上述结果集:

WITH aggregated AS (
  SELECT
    PubID    = COALESCE(CAST(PubID AS varchar(10)), 'Total'),
    Location = COALESCE('Local_' + CAST(LocationID AS varchar(10)), 'Total'),
    QTY      = SUM(CASE [Transaction] WHEN 'Add' THEN QTY ELSE -QTY END)
  FROM dbo.InventoryLog
  GROUP BY CUBE(PubID, LocationID)
)
SELECT
  PubID,
  Local_1,
  Local_2,
  Local_3,
  Total
FROM aggregated
PIVOT (
  MAX(QTY)
  FOR Location IN (Local_1, Local_2, Local_3, Total)
) AS p
;

此查询将返回 NULL 的缺失组合(PubID, LocationID)。如果您想返回 0,请将 COALESCE 应用到 SUM 的定义中的结果aggregated

于 2014-03-04T20:06:14.037 回答