2014-02-19 2 views
1

Почему мои предложения здесь проигнорированы, они суммируют счета-фактуры, независимо от значений, введенных в качестве параметров, потраченных на это часов и безумных!Как использовать предложение WHERE с помощью PIVOT

ALTER PROCEDURE [dbo].[Usp_custom_dash_metric_invoicespend] 
    @CompanyGUID UNIQUEIDENTIFIER, 
    @UserGUID UNIQUEIDENTIFIER, 
    @CompanyUserGUID UNIQUEIDENTIFIER, 
    @InvoiceYearFrom CHAR(4), 
    @InvoiceYearTo CHAR(4), 
    @CompanySupplierGUID UNIQUEIDENTIFIER 
AS 
BEGIN 
WITH _d 
    AS (SELECT a.totalgrossvaluehome1 AS tgvh1, 
       invoicedate   AS ind, 
       c.guid     AS cug, 
       a.companysupplierguid AS cus, 
       c.userguid    AS ug, 
       b.guid     AS cg 
     FROM invoices a (nolock) 
       JOIN companies b (nolock) 
       ON (a.companyguid = b.guid) 
       JOIN companyusers c (nolock) 
       ON (c.userguid = a.createdbyguid) 
     WHERE a.invoicedate BETWEEN Cast(Isnull(NULL, Cast(Datepart(year 
             , 
             Dateadd( 
             year, -1, 
               Getdate()))AS NVARCHAR( 
             max 
             ))) 
             + '-01-01' AS DATETIME) AND 
            Cast( 
       Isnull(NULL, Cast(Datepart(year, 
       Getdate() 
      )AS 
       NVARCHAR(max))) 
       + '-12-31' AS DATETIME) 
       AND c.guid = @CompanyUserGUID 
       OR @CompanyUserGUID IS NULL 
        AND a.companysupplierguid = @CompanySupplierGUID 
       OR @CompanySupplierGUID IS NULL 
        AND c.userguid = @UserGUID 
       OR @UserGUID IS NULL 
        AND a.companyguid = @CompanyGUID 
       OR @CompanyGUID IS NULL) 
SELECT * 
FROM (SELECT Year(ind)     AS [ayear], 
      LEFT(Datename(month, ind), 3)AS [amonth], 
      Isnull(tgvh1, 0)    AS Amount 
     FROM _d 
     WHERE cug = @CompanyUserGUID 
       OR @CompanyUserGUID IS NULL 
       AND cus = @CompanySupplierGUID 
       OR @CompanySupplierGUID IS NULL 
       AND ug = @UserGUID 
       OR @UserGUID IS NULL 
       AND cg = @CompanyGUID 
       OR @CompanyGUID IS NULL)s 
    PIVOT (Sum(amount) 
      FOR [amonth] IN (jan, 
          feb, 
          mar, 
          apr, 
          may, 
          jun, 
          jul, 
          aug, 
          sep, 
          oct, 
          nov, 
          dec))AS pivotal 
WHERE pivotal.ayear >= Isnull(@InvoiceYearFrom, Datepart(year, 
               Dateadd(year, -1, 
                 Getdate() 
               ))) 
    AND pivotal.ayear <= Isnull(@InvoiceYearTo, Datepart(year, Getdate( 
               )) 
         ) 
ORDER BY [ayear] 
END 

Именно этот бит конкретно:

WHERE a.invoicedate BETWEEN Cast(Isnull(@InvoiceDateFrom, Cast(Datepart(year 
             , 
             Dateadd( 
             year, -1, 
               Getdate()))AS NVARCHAR( 
             max 
             ))) 
             + '-01-01' AS DATETIME) AND 
            Cast( 
       Isnull(@InvoiceDateTo, Cast(Datepart(year, 
       Getdate() 
      )AS 
       NVARCHAR(max))) 
       + '-12-31' AS DATETIME) 
       AND c.guid = @CompanyUserGUID 
       OR @CompanyUserGUID IS NULL 
        AND a.companysupplierguid = @CompanySupplierGUID 
       OR @CompanySupplierGUID IS NULL 
        AND c.userguid = @UserGUID 
       OR @UserGUID IS NULL 
        AND a.companyguid = @CompanyGUID 
       OR @CompanyGUID IS NULL) 

например, данные, возвращаемые в оси подытоживает все данные (я предполагал, потому что он принимает данные от CTX, что она будет включать в себя отфильтрованные данные, поэтому я ожидал бы, если бы я прошел через @Userguid = (реальный идентификатор пользователя), это ограничило бы счетные счета счетами только для пользователя ... это не: '(

+0

При выполнении запроса без шарнирной части вы возвращаетесь правильным с ИНЕК? – Taryn

+0

Да, данные, возвращенные из CTX, фильтруются правильно. –

ответ

1

Глядя на ваш пункт WHERE, Я вижу, что OR используется для разгруппировки заявления. Я думаю, что вы хотите заменить последний кусок вашего WHERE пункта со следующим (обратите внимание, что вы хотите дополнительные закрытия скобки позже, чтобы закончить КТР):

AND (c.guid = @CompanyUserGUID -- Added opening paren (required) 
OR (@CompanyUserGUID IS NULL  -- Added parens around group (optional) 
    AND a.companysupplierguid = @CompanySupplierGUID) 
OR (@CompanySupplierGUID IS NULL -- Added parens around group (optional) 
    AND c.userguid = @UserGUID) 
OR (@UserGUID IS NULL   -- Added parens around group (optional) 
    AND a.companyguid = @CompanyGUID) 
OR @CompanyGUID IS NULL)   -- Added closing paren 

Update

Глядя на содержимое вашего предложения WHERE немного ближе, я думаю, вы можете добавить кучу дополнительных группировок. Из того, что я могу сказать, я думаю, что ваше намерение состоит только в проверке параметра GUID, если все предыдущие Параметры GUID были NULL. Ваше текущее предложение WHERE проверяет все параметры GUID, в которых предыдущий (но не обязательно один до этого) был NULL. Эти группы должны решить эту проблему.

AND (c.guid = @CompanyUserGUID 
    OR ( @CompanyUserGUID IS NULL 
     AND (a.companysupplierguid = @CompanySupplierGUID 
      OR ( @CompanySupplierGUID IS NULL 
       AND (c.userguid = @UserGUID 
        OR ( @UserGUID IS NULL 
        AND ( a.companyguid = @CompanyGUID 
         OR @CompanyGUID IS NULL)))))))) 

End Update

Насколько я понимаю порядок операций в SQL-сервере, скобки вокруг отдельных @param IS NULL OR column = @param положений не является необходимой (кроме создания ваших намерений яснее). С другой стороны, необходимо открывать и закрывать круглые скобки вокруг группировки в целом. Без этого ваш SQL проверяет (a.invoicedate BETWEEN ... AND c.guid = @CompanyUserGUID) OR [GUID clauses...]

Кроме того, я настоятельно рекомендую очистить свой SQL, который получает ваши диапазоны времени. Вы можете упростить их совсем немного (и сделать код более удобным для чтения и диагностики) с помощью следующей:

-- "Start of last year": 
--  Get the number of years from 0 (1900-01-01) to this year from 0 
--  Then add add that many years (minus 1 for last year) back to 0 
DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE())-1, 0) 
-- "End of this year": Get "the start of next year" and subtract one day 
DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE())+1, 0)) 

Обратите внимание, что если ваш invoicedate столбец не укорачивает время, текущая логика фактически исключает записи на 2014-12 -31, из-за отметки времени в вашем фильтре 00:00:00. Если это так, я рекомендую только начать с начала следующего года.

+0

Это преднамеренно, я хочу, чтобы он провалился и по умолчанию имеет значение null до тех пор, пока он не будет параметризован. –

+0

@JoshuaHolden Я удалил заявление об использовании 'ISNULL' и обновил свой ответ тем, что, по вашему мнению, вызывает ваши проблемы. –

+0

-> Спасибо, это были мои parens! –

1

Я думаю, вы должны добавить соответствующие скобки здесь, группируя ИЛИ & И условия являются важными

AND c.guid = @CompanyUserGUID 
OR @CompanyUserGUID IS NULL 
AND a.companysupplierguid = @CompanySupplierGUID 
    OR @CompanySupplierGUID IS NULL 
       AND c.userguid = @UserGUID 
      OR @UserGUID IS NULL 
       AND a.companyguid = @CompanyGUID 
      OR @CompanyGUID IS NULL 
Смежные вопросы