2016-04-14 2 views
0

В настоящее время у меня есть шесть запросов, в которых я беру результаты и использую таблицу для вычисления двух разных конечных процентов. Я считаю, что это можно сделать в одном запросе и без электронной таблицы, но я недостаточно разбираюсь в SQL, чтобы понять это. Я надеюсь на какое-то направление от удивительных богов SQL здесь, на SO.TSQL вычисление из комбинированных запросов

У нас есть несколько мест, и вычислить Past Due% и просрочено Fallout%, за место, основанный на среднем двух других процентов:

  • просроченными, Долларов ÷ Прогнозируемые Долларов = Просроченные, Поплавок%
  • просроченными, Units ÷ Всего активных единиц = просрочено Unit%
  • (просрочено Unit% + просрочено доллар%)/2 = просрочено%

Fallout использует одни и те же вычисления, но смотрит на то, что суммы будут завтра.

РЕШИТЬ: я потратил время на изучение подзапросов, и присоединился к ним в STID. Спасибо всем, кто помог мне и помог мне в правильном направлении .

Вот мой окончательный код:

SET DATEFIRST 1; 
DECLARE @Today date = dbo.getdateparam(92,999); 
DECLARE @TodayNum int = DATEPART(dw, @Today); 
DECLARE @Saturday date = DATEADD(DAY, ([email protected])%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 
+0

Без чтения всех этих деталей. У меня есть простой вопрос. Во всех этих запросах есть какое-либо поле (столбец из вашей таблицы), которое связывает все эти запросы вместе? Если это так, ваш ответ прост, вы присоединяетесь ко всем этим запросам, используя производный запрос. похоже, что ваш результирующий набор говорит «да» ... вы бы сделали «SELECT .. FROM FirstQuery t1 JOIN (SELECT .. FROM YourSecondQuery) t2 ON t2.SomeID = t1.SomeID', и вы продолжаете оттуда. – JonH

+0

@JonH Все имеют общее поле Agreemnt.STID, EXCEPT для ProjectedDollars, которое запрашивает одну таблицу. – thelincster

+0

для того, чтобы связывать таблицы, должны быть какие-то отношения, если у вас нет отношений, как вы ожидаете, что сервер sql даст вам этот запрос ... он не может, потому что вы не можете сказать это, что хотите. Вам нужно установить, как эта таблица связана с другими таблицами. – JonH

ответ

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 
+0

Это несколько похоже на то, что мне может понадобиться, но тогда как бы я вычислил конечные проценты? – thelincster

+0

Я предполагаю, что я не понимаю, что если я использую CTE для каждого запроса и объединяю их вместе на STID, как мне создавать переменные из результатов запроса, запускать мои вычисления, а затем выводить результаты запроса И рассчитанные результаты все вместе. У меня просто не было этого момента «ах ха» ...:/ – thelincster

+0

@thelincster вам не нужны переменные. Вы можете делать вычисления в предложении select окончательного запроса. – dotjoe

0

Вы никогда не задавать значения переменных в любую реальную стоимость, то вы продолжите, чтобы выбрать ненужные переменный в неактуальном ЗЕЬЕСТЕ.

в следующей строке

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

Вы не о том, где s.DueDate приходит. Это обыкновение даже компилировать.

В этом ВЫБРАТЬ таблица совершенно неуместные

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 
+0

Извините, что я не знаю ... если бы я пошел этим путем с переменной в выражении select, тогда мне пришлось бы запускать несколько запросов? Как бы я их складывал? – thelincster

+0

Чтобы уложить их, вы следуете по пути @dotjoe. Сначала вы выбираете, а затем назначаете в последнем SELECT своего exmaple. –

+0

После повторного чтения предложения @dotjoe, я думаю, я понимаю. То, что я до сих пор не могу обойти, состоит в том, как вычислить два последних процента от этих вычислений и вывести данные. – thelincster

0

Моя проблема была нехватка знаний и понимания SQL, который я на улучшение. Вот что я закончил с тем, что дало мне результат, который я хотел, будь он наиболее эффективным или нет.

SET DATEFIRST 1; 
DECLARE @Today date = dbo.getdateparam(92,999); 
DECLARE @TodayNum int = DATEPART(dw, @Today); 
DECLARE @Saturday date = DATEADD(DAY, ([email protected])%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 
Смежные вопросы