从组合查询计算TSQL

时间:2016-04-14 17:28:32

标签: sql tsql

我目前有六个查询,我在其中查看结果并使用电子表格计算两个不同的最终百分比。我相信它可以在一个查询中完成,并且没有电子表格,但我在SQL中不够了解它。我希望在这里有来自神奇的SQL神的方向。

我们有多个地点,并根据其他两个百分比的平均值计算每个地点的过期时间百分比和过期时间辐射百分比:

  • 过期美元÷预计美元= 过期浮动%
  • 过期单位÷总有效单位= 过期单位%
  • 过期的单位% + 过期的美元%)/ 2 = 过期的%

Fallout使用相同的计算,但会查看明天的金额。

  

已解决:我花时间了解子查询,并由STID加入。感谢所有协助并帮助指导我的人   正确的方向。

这是我的最终代码:

SET DATEFIRST 1;
DECLARE @Today date = dbo.getdateparam(92,999);
DECLARE @TodayNum int = DATEPART(dw, @Today);
DECLARE @Saturday date = DATEADD(DAY, (6-@TodayNum)%7, @Today);
DECLARE @PrevSat date = DATEADD(DAY, -7, @Saturday);

Select store.STID As Store,
  Proj.ProjRent As Projected,
  PDRent.PastDueDollars As PDRent,
  UOR.Units As UOR,
  PDUnits.UnitsPD As PDUnits,
  (PDRent.PastDueDollars / Proj.ProjRent) * 100 As FloatPerc,
  (Cast(PDUnits.UnitsPD As Decimal) / Cast(UOR.Units As Decimal)) *
  100 As UnitPerc,
  Cast(Round((((PDRent.PastDueDollars / Proj.ProjRent) * 100) +
  ((Cast(PDUnits.UnitsPD As Decimal(18,4)) / Cast(UOR.Units As Decimal(18,4))) *
  100)) / 2, 2) As Decimal(18,2)) As PDPerc,
  Reds.RedsPD As PDReds,
  Round(Cast(Reds.RedsPD As Float) / Cast(UOR.Units As Float) * 100,
  2) As RedsPerc
From 
 -- Stores
(Select Distinct Stores.STID,
    Stores.StoreName,
    Stores.EMail,
    Stores.ManagersName
  From Stores
  Where Stores.STID Not In (7, 999)) As store

  -- Projected Rent
  Left Join (Select CashProj.STID,
    Sum(CashProj.ProjectedRental) As ProjRent
  From CashProj
  Where CashProj.ProjectionDate Between DateAdd(mm, DateDiff(mm, 0, @Today),
    0) And DateAdd(mm, DateDiff(mm, 0, @Today) + 1, 0)
  Group By CashProj.STID) As Proj On store.STID = Proj.STID

  -- Past Due Float
  Left Join (Select Agreemnt.STID As STID,
    Sum(DateDiff(d, Agreemnt.DueDate, (Case DatePart(dw, @Today)
      When '1' Then DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw,
      @Today)) % 7, @Today)) When '6' Then @Today
      Else DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today)
    End)) * Round(Agreemnt.WeeklyRate / 7, 2)) As PastDueDollars,
    DatePart(dw, @Today) As TodayNum,
    DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7,
    @Today)) As PrevSat,
    DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today) As Saturday
  From Agreemnt
  Where Agreemnt.AStatID = 1 And Agreemnt.DueDate < (Case DatePart(dw,
      @Today)
      When '1' Then DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw,
      @Today)) % 7, @Today)) When '6' Then @Today
      Else DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today)
    End) And Agreemnt.RentToRent = 0
  Group By Agreemnt.STID) As PDRent On store.STID = PDRent.STID

  -- Units On Rent
  Left Join (Select Invntry.STID,
    Cast(Count(Invntry.StockNumber) As Int) As Units
  From Invntry
    Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
      Invntry.STID = AgreHist.STID
    Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
      Agreemnt.AgreeID = AgreHist.AgreeID And Agreemnt.AStatID =
      AgreHist.AStatID
  Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
    Agreemnt.AStatID = 1
  Group By Invntry.STID) As UOR On store.STID = UOR.STID

  -- Past Due Units
  Left Join (Select Invntry.STID,
    Cast(Count(Invntry.StockNumber) As Int) As UnitsPD
  From Invntry
    Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
      Invntry.STID = AgreHist.STID
    Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
      Agreemnt.AgreeID = AgreHist.AgreeID And AgreHist.AStatID =
      Agreemnt.AStatID
  Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
    Agreemnt.AStatID = 1 And Agreemnt.DueDate < (Case @TodayNum When '1' Then @PrevSat When '6' Then @Today Else @Saturday End) And Agreemnt.RentToRent = 0
  Group By Invntry.STID) As PDUnits On store.STID = PDUnits.STID

  -- Reds
  Left Join (Select Invntry.STID,
    Count(Invntry.StockNumber) As RedsPD
  From Invntry
    Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
      Invntry.STID = AgreHist.STID
    Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
      Agreemnt.AgreeID = AgreHist.AgreeID And Agreemnt.AStatID =
      AgreHist.AStatID
  Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
    Agreemnt.AStatID = 1 And Agreemnt.DueDate < DateAdd(day, -15, Case
      Cast(DatePart(dw, @Today) As Int)
      When '1' Then Cast(DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw,
      @Today)) % 7, @Today)) As Date)
      When '6' Then Cast(@Today As Date)
      Else Cast(DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today) As
      Date) End) And Agreemnt.RentToRent = 0
  Group By Invntry.STID) As Reds On store.STID = Reds.STID
Order By Store

3 个答案:

答案 0 :(得分:0)

您永远不会将变量设置为任何实际值,您将继续在无关的SELECT语句中选择无用变量。

在以下一行

Set @pdD = Sum( Case When a.DueDate < GetDate() Then DateDiff(d,a.DueDate,@runDate) * (a.WeeklyRate/7) )

您没有说明s.DueDate的来源。它甚至不会编译。

在此SELECT中,该表完全不相关

Select a.STID as STID,
@pdU As PastDueUnits,
@activeU As ActiveUnits,
@pdD As PastDueDollars,
@projRent As ProjRent,
@pdP As PastDuePerc,
@foU As FalloutUnits,
@foD As FalloutDollars,
@foP As FalloutPerc

FROM Agreemnt a INNER JOIN CashProj on a.STID = CashProj.STID JOIN Invntry i ON a.STID = i.STID JOIN AgreHist h On i.InvID = h.InvID And i.STID = h.STID INNER JOIN Agreemnt a On a.STID = h.STID AND a.AgreeID = h.AgreeID AND a.AStatID = h.AStatID 
WHERE a.RentToRent = 0 AND i.InvStatID = 11 AND i.DisposalDate IS NULL AND a.AStatID = 1 AND a.DueDate < DateAdd(d, @runDate, GetDate())
GROUP BY a.STID
ORDER BY a.STID

这是在尝试使用变量进行计算之前如何设置值的示例。

    DECLARE @dayNum INT;
SET @dayNum = datepart(dw, getdate());

Select Invntry.STID,
  @foU = COUNT(Invntry.StockNumber) 
From Invntry
  Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
    Invntry.STID = AgreHist.STID
  Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And Agreemnt.AgreeID =
    AgreHist.AgreeID And Agreemnt.AStatID = AgreHist.AStatID
Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
  Agreemnt.AStatID = 1 And Agreemnt.DueDate < DateAdd(d, Case @dayNum When '1' Then -2 When '2' Then 1 When '3' Then 1 When '4' Then 1
    When '5' Then 1 When '6' Then 0 When '7' Then -1 End, GetDate()) And Agreemnt.RentToRent = 0
Group By Invntry.STID

答案 1 :(得分:0)

你不能使用这样的变量,你不能在一个聚合查询中这样做,因为它会创建一个巨大的笛卡尔积,并给你不正确的结果。

您可以为列出的每个查询使用CTE或子查询,然后在STID上将它们连接在一起并应用您的公式。

...示例

/* declare all variables here */
DECLARE @dayNum INT;
SET @dayNum = datepart(dw, getdate());

with PastDueDollars as (
    select ... from ... group by STID
), ProjectedDollers as (
    select ... from ... group by STID
), PastDueUnits as (
    select ... from ... group by STID
), preFinal as (

    select
        PastDueDollarRatio = pdd.PastDueDollars / pd.ProjRent,
        PastDueUnitRatio = pdu.UnitsPD / tau.TotalActiveUnits
        /* add the other calculations */
    from
        PastDueDollars pdd
        inner join ProjectedDollers pd on pdd.STID = pd.STID
        inner join PastDueUnits pdu on pdu.STID = pd.STID
        /* join more CTEs */
)

select
    f.*,
    PastDueRatio = (f.PastDueDollarRatio + f.PastDueUnitRatio) / 2
    /* and so on for the other calculations of calculations... */
from
    preFinal f

答案 2 :(得分:0)

我的问题是缺乏对SQL的了解和理解,我正在改进。这就是我最终得到的结果,它给了我想要的结果,无论效率是否最高。

 SET DATEFIRST 1;
 DECLARE @Today date = dbo.getdateparam(92,999);
 DECLARE @TodayNum int = DATEPART(dw, @Today);
 DECLARE @Saturday date = DATEADD(DAY, (6-@TodayNum)%7, @Today);
 DECLARE @PrevSat date = DATEADD(DAY, -7, @Saturday);

 Select store.STID As Store,
   Proj.ProjRent As Projected,
   PDRent.PastDueDollars As PDRent,
   UOR.Units As UOR,
   PDUnits.UnitsPD As PDUnits,
   (PDRent.PastDueDollars / Proj.ProjRent) * 100 As FloatPerc,
   (Cast(PDUnits.UnitsPD As Decimal) / Cast(UOR.Units As Decimal)) * 100 As UnitPerc,
   Cast(Round((((PDRent.PastDueDollars / Proj.ProjRent) * 100) + ((Cast(PDUnits.UnitsPD As Decimal(18,4)) / Cast(UOR.Units As Decimal(18,4))) * 100)) / 2, 2) As Decimal(18,2)) As PDPerc,
   Reds.RedsPD As PDReds,
   Round(Cast(Reds.RedsPD As Float) / Cast(UOR.Units As Float) * 100,2) As RedsPerc
 From 
  -- Stores
 (Select Distinct Stores.STID,
     Stores.StoreName,
     Stores.EMail,
     Stores.ManagersName
   From Stores
   Where Stores.STID Not In (7, 999)) As store

  -- Projected Rent
   Left Join (Select CashProj.STID,
     Sum(CashProj.ProjectedRental) As ProjRent
   From CashProj
   Where CashProj.ProjectionDate Between DateAdd(mm, DateDiff(mm, 0, @Today),0) And DateAdd(mm, DateDiff(mm, 0, @Today) + 1, 0)
   Group By CashProj.STID) As Proj On store.STID = Proj.STID

  -- Past Due Float
   Left Join (Select Agreemnt.STID As STID,
     Sum(DateDiff(d, Agreemnt.DueDate, (Case DatePart(dw, @Today) When '1' Then DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today)) When '6' Then @Today
       Else DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today) End)) * Round(Agreemnt.WeeklyRate / 7, 2)) As PastDueDollars,
     DatePart(dw, @Today) As TodayNum,
     DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7,
@Today)) As PrevSat,
     DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today) As Saturday
   From Agreemnt
   Where Agreemnt.AStatID = 1 And Agreemnt.DueDate < (Case DatePart(dw, @Today) When '1' Then DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today)) When '6' Then @Today Else DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today) End) And Agreemnt.RentToRent = 0
   Group By Agreemnt.STID) As PDRent On store.STID = PDRent.STID

  -- Units On Rent
   Left Join (Select Invntry.STID,
     Cast(Count(Invntry.StockNumber) As Int) As Units
   From Invntry
     Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
       Invntry.STID = AgreHist.STID
     Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
       Agreemnt.AgreeID = AgreHist.AgreeID And Agreemnt.AStatID =
       AgreHist.AStatID
   Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And Agreemnt.AStatID = 1
   Group By Invntry.STID) As UOR On store.STID = UOR.STID

  -- Past Due Units
   Left Join (Select Invntry.STID,
     Cast(Count(Invntry.StockNumber) As Int) As UnitsPD
   From Invntry
     Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
       Invntry.STID = AgreHist.STID
     Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
       Agreemnt.AgreeID = AgreHist.AgreeID And AgreHist.AStatID =
       Agreemnt.AStatID
   Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
     Agreemnt.AStatID = 1 And Agreemnt.DueDate < (Case @TodayNum When '1' Then @PrevSat When '6' Then @Today Else @Saturday End) And Agreemnt.RentToRent = 0
   Group By Invntry.STID) As PDUnits On store.STID = PDUnits.STID

  -- Reds
   Left Join (Select Invntry.STID,
     Count(Invntry.StockNumber) As RedsPD
   From Invntry
     Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And Invntry.STID = AgreHist.STID
     Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And Agreemnt.AgreeID = AgreHist.AgreeID And Agreemnt.AStatID = AgreHist.AStatID
   Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And Agreemnt.AStatID = 1 And Agreemnt.DueDate < DateAdd(day, -15, Case Cast(DatePart(dw, @Today) As Int) When '1' Then Cast(DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today)) As Date) When '6' Then Cast(@Today As Date) Else Cast(DateAdd(DAY, (6 - DatePart(dw, @Today)) % 7, @Today) As Date) End) And Agreemnt.RentToRent = 0
   Group By Invntry.STID) As Reds On store.STID = Reds.STID
 Order By Store