如何从复杂的数据库中获取记录?

时间:2019-02-16 09:37:20

标签: sql sql-server tsql

我需要一次从MSSQL使用多个表获取多个记录和单个记录。我需要从中收集数据的表如下:

1. tblExpenseType :
--> ExpenseTypeId | ExpenseTypeName
-->      1        | OVERTIME EXP.
-->      2        | REPAIRING EXP.
-->      3        | LU EXP.

2. tblMemoDetails :
--> MemoID | MemoNumber | FkTruckId
--> 1011   | 1          | 5
--> 1012   | 2          | 6
--> 1013   | 3          | 5
--> 1014   | 4          | 7

3. tblMemoExpense :
--> FkMemoNumber | FkExpenseTypeId | Amount
--> 1            | 1               | 150
--> 1            | 3               | 225
--> 2            | 1               | 50
--> 2            | 2               | 100
--> 2            | 3               | 150

4. tblMemoTrips :
--> FkTripId | FkMemoNumber | TripAmount
--> 11       | 1            | 1000
--> 9        | 2            | 500
--> 3        | 2            | 100
--> 4        | 2            | 2000

我正尝试使用以下逻辑来获取数据,但这使我感到困惑:


with MemoList
As
(select
    _jpMemo.MemoId as memoId
from TMS_JPMemo _jpMemo
where _jpMemo.FkTruckId = 5)

select 
    ML.memoId
    --,ME.FkExpenseTypeId 
    ,ME.Amount 
    ,ET.ExpenseTypeName
from TMS_MemoExpense ME
join MemoList ML on ML.memoId = ME.FkMemoId
join TMS_ExpenseTypes ET on ET.ExpenseTypeId = ME.FkExpenseTypeId

我需要结果,例如,如果我选择FkTruckId 5,它将显示以下结果。 对于FkTruckId 5,我需要以下结果:

MemoNumber | TripDetails | TripAmount | OVERTIME | REPAIRING | LU
   1       |    11       |     1000   |   150    |    --     | 225
           |    Total    |     1000   |   150    |    --     | 225

如果我选择FkTruckId 6,它将显示类似以下结果:

MemoNumber | TripDetails | TripAmount | OVERTIME | REPAIRING | LU
   2       |    9        |     500    |   --    |    --     | --
           |    3        |     100    |   --    |    --     | --
           |    4        |     2000   |   50    |    100    | 150
           |    Total    |     2600   |   50    |    100    | 150

因此,这让我感到困惑,如何解决这个问题以及如何从表中获得这种类型的复杂数据。

3 个答案:

答案 0 :(得分:0)

您可以使用一系列JOIN来关联表,然后使用条件聚合来轮换数据。这意味着要枢转的列数是固定的(如果将更多的值添加到表tblExpenseType中,则需要对查询进行调整):

SELECT
    md.MemoNumber,
    mt.FkTripId AS TripDetails,
    mt.TripAmount,
    MAX(CASE WHEN et.ExpenseTypeName = 'OVERTIME EXP.'   THEN me.amount END) AS OVERTIME,
    MAX(CASE WHEN et.ExpenseTypeName = 'REPARINING EXP.' THEN me.amount END) AS REPARING,
    MAX(CASE WHEN et.ExpenseTypeName = 'LU EXP.'         THEN me.amount END) AS LU
FROM
    tblMemoDetails AS md
    LEFT JOIN tblMemoExpense AS me ON me.FkMemoNumber  = md.MemoNumber
    LEFT JOIN tblMemoTrips   AS mt ON mt.FkMemoNumber  = md.MemoNumber
    LEFT JOIN tblExpenseType AS et ON et.ExpenseTypeId = me.FkExpenseTypeId
GROUP BY 
    md.MemoNumber,
    mt.FkTripId AS TripDetails,
    mt.TripAmount

答案 1 :(得分:0)

有条件的聚合是必经之路。我认为查询看起来像这样:

SELECT md.TruckId, md.MemoNumber,
       COALESCE(mt.FkTripId, 'Total') AS TripDetails, mt.TripAmount,
       SUM(CASE WHEN et.ExpenseTypeName = 'OVERTIME EXP.' THEN me.amount ELSE 0 END) AS OVERTIME,
       SUM(CASE WHEN et.ExpenseTypeName = 'REPARINING EXP.' THEN me.amount ELSE 0 END) AS REPARING,
       SUM(CASE WHEN et.ExpenseTypeName = 'LU EXP.' THEN me.amount ELSE 0 END) AS LU
FROM tblMemoDetails md LEFT JOIN
     tblMemoExpense me
     ON me.FkMemoNumber = md.MemoNumber LEFT JOIN
     tblMemoTrips mt
     ON mt.FkMemoNumber = md.MemoNumber LEFT JOIN
     tblExpenseType et
     ON et.ExpenseTypeId = me.FkExpenseTypeId
WHERE md.TruckId = @TruckId
GROUP BY GROUPING SETS ( (md.TruckId, md.MemoNumber, mt.FkTripId, mt.TripAmount), () );

GROUPING SETS生成总数。

答案 2 :(得分:0)

每个备忘录显示两个不同的内容:

  1. 备忘录的行程及其行程量
  2. 备忘录的费用

除了属于同一个备忘录外,两者没有关联,即每次旅行没有任何花费。所以实际上是您要显示的两个不同的东西。进行两个单独的查询。您可以将它们与&EO.method (&parm1, ...) 粘合在一起,因为您显然希望它们都在一个查询结果中。像这样:

UNION ALL