如何使窗口函数在WHERE子句中工作

时间:2018-07-11 08:07:04

标签: sql-server

我知道“窗口函数只能出现在select或ORDER BY句柄中”主题上有很多线程,但是我已经通读了它们,只是似乎没有任何技巧可以为我工作。所以我走了。

您可以在下面看到我的查询。我强调了查询的一部分,它“引起”我一些问题。问题是我想得到

LocalCurrentAmount不在-1.000000和1.000000之间”

以某种方式。我已经尝试过CTE版本,但是不知何故,我的声明表和详细信息视图开始引起问题。

非常感谢您的帮助! 贾尼斯(Jaanis)


declare @exceptions1 table (CustomerCode varchar(7), Exception_comment varchar(15));
insert into @exceptions1 (CustomerCode, Exception_comment)
VALUES
(3514437,'Exception'),(3500977,'Exception'),(3295142,'Exception'), ...

declare @exceptions2 table (CustomerCode2 varchar(7), Exception_comment2 varchar(15));
insert into @exceptions2 (CustomerCode2, Exception_comment2)
VALUES
(3390437,'VIP SE')  ,(3390438,'VIP SE') ,(3390481,'VIP SE'),    ...

declare @exceptions3 table (CustomerCode3 varchar(7), Exception_comment3 varchar(15));
insert into @exceptions1 (CustomerCode, Exception_comment)
VALUES 
(1530350, 'DK Exception'), (1533834, 'DK Exception'), (1530002, 'DK Exception'), ...

with Details as 
(
    select ard.AccountsReceivableHeaderID, sum(ard.TransactionAmountOC) as DetailAmountOC , Max(DetailSequenceCode) as DetailSequenceCode, Max( ard.BatchDate) as BatchDate
    from dmbase.fAccountsReceivableDetail ard
    join dmbase.fAccountsReceivable arh on ard.AccountsReceivableHeaderID = arh.AccountsReceivableID
    where ard.BatchDate <= getdate()
    group by AccountsReceivableHeaderID 
)

SELECT 
    comp.CompanyCode
    ,convert(varchar(10),ar.InvoiceDate, 103) as Invoice_date -- dd/MM/yyyy format
    ,case 
        when ar.IsCreditMemo = 'Y' then 'Memo (Credit/Debit)' 
        when ar.InvoiceCode = '0' then 'Payment' 
        else 'Invoice' 
    end as Description
    ,isnull(cm.SummaryInvoiceCode, ar.InvoiceSummaryCode) InvoiceSummaryCode
    ,case
        when len(ar.InvoiceSequenceCode) = '1' then CONCAT(ar.InvoiceCode,'-000',ar.InvoiceSequenceCode)
        when len(ar.InvoiceSequenceCode) = '2' then CONCAT(ar.InvoiceCode,'-00',ar.InvoiceSequenceCode)
        when len(ar.InvoiceSequenceCode) = '3' then CONCAT(ar.InvoiceCode,'-0',ar.InvoiceSequenceCode)
        else CONCAT(ar.InvoiceCode,'-',ar.InvoiceSequenceCode)
    end as Invoice#
    ,**(ar.OriginalInvoiceAmountOC
    + 
    case 
        when row_number() over (partition by AccountsReceivableID order by ar.InvoiceCode) = 1 then isnull(vat.vatAdjustment, 0) 
        else 0 
    end
    + 
    coalesce(det.DetailAmountOC, 0)) * coalesce(cer.CurrencyExchangeRate, ar.CurrencyExchangeRate) AS LocalCurrentAmount**
    ,(ar.OriginalInvoiceAmountOC
    + 
    case 
        when row_number() over (partition by AccountsReceivableID order by ar.InvoiceCode) = 1 then isnull(vat.vatAdjustment, 0) 
        else 0 
    end
    + coalesce(det.DetailAmountOC, 0)) AS CurrentAmount
    ,ar.OriginalInvoiceAmountOC
    + 
    case 
        when row_number() over (partition by AccountsReceivableID order by ar.InvoiceCode) = 1 then isnull(vat.vatAdjustment, 0) 
        else 0 
    end as OriginalInvoiceAmountOC
    ,ar.InvoiceCurrencyCode
    ,cust.CustomerCode
    ,upper(cust.CustomerName) as CustomerName
from 
    dmbase.fAccountsReceivable ar
    INNER JOIN dmbase.dlocation loc
        ON loc.LocationID = ar.LocationID
    INNER JOIN dmbase.dCustomer cust
        ON cust.CustomerID = ar.CustomerID
    LEFT JOIN dmbase.VatAdjustment vat
        on ar.InvoiceCode = vat.contractNumber 
        and ar.InvoiceSequenceCode = vat.invoiceSequence 
        and cust.CustomerCode = vat.CustomerNumber
        and loc.CompanyCode = vat.companyCode
    inner join dmbase.dCompany comp
        on (ar.CompanyID = comp.CompanyID)
    left join dmbase.dAccountsReceivableInvoiceStatus aris 
        on (aris.ARInvoiceStatusAMID=ar.ARInvoiceStatusAMID)
    left hash join Details det
        on (ar.AccountsReceivableID = det.AccountsReceivableHeaderID)
    left join dmbase.dCurrencyExchangeRate cer
        on (comp.CompanyCode = cer.CompanyCode 
        and ar.InvoiceCurrencyCode = cer.CurrencyCode
        and case ar.InvoiceDate when '1900-01-01' then getdate() else ar.InvoiceDate end between cer.ValidFrom and cer.ValidTo)
    left join dmbase.fContractClosedHeader ccd  
        on  ccd.ContractNumber = ar.InvoiceCode 
        and ccd.ContractSeqNumber = ar.InvoiceSequenceCode 
        and ccd.CompanyID = ar.CompanyID  
        and ccd.ContractNumber!='0' 
        and ccd.CreditMemoContractNumber != '0'
    left join dmbase.fAccountsReceivableHeader cm 
        on ccd.CreditMemoContractNumber  = cm.ContractNumber 
        and ccd.CreditMemoSequenceCode = cm.ContractSeqNumber 
        and cm.CompanyID = ccd.CompanyID
where 
    (aris.ARInvoiceStatusCode = 'OP' or (ar.LastPaymentDate >= getdate()) 
    or (ar.TotalAdjustmentsAmountOC <> 0 and ar.CurrentAmountLC = 0 
    and (ar.OriginalInvoiceAmountOC + isnull(vat.vatAdjustment, 0) ) + coalesce(det.DetailAmountOC, 0) <> 0)
    )
    and ar.OriginalInvoiceAmountOC <= 0
    and ar.IsCreditMemo = 'Y' -- ainult Memo (Credit/Debit)
    and cust.InternalCustomerType = 'External'
    and cust.CustomerName not in ('RR AJM', 'RAMIRENT', 'Ramirent')
    and cust.CustomerName not like '%[7][0-9][0-9][0-9]%'  
    and ar.InvoiceDate <= EOMONTH(getdate(),-3
    and cust.CustomerCode NOT IN
        (select CustomerCode from @exceptions1
        union
        select CustomerCode2 from @exceptions2
        union
        select CustomerCode3 from @exceptions3)
order by Invoice_date

1 个答案:

答案 0 :(得分:0)

使用Window函数时,就像您在帖子中所说的那样,不能在Ubuntu 16.04.4 LTS子句中使用它。因此,常见的解决方案是使用CTE并在其外部的WHERE中引用它。我使用了您的CTE,但是,没有任何示例数据,这完全是个猜测。我还为您留下了很多评论,并更改了SQL的其他部分,因为您拥有的某些子句会影响查询的性能。

WHERE

值得注意的是,上述sql是未经测试的。我无权访问您的服务器或数据,因此我纯粹是依靠“我的眼睛”来记录任何错误。