Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何使窗口函数在WHERE子句中工作_Sql Server - Fatal编程技术网

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

Sql server 如何使窗口函数在WHERE子句中工作,sql-server,Sql Server,我知道窗口函数上有相当多的线程只能出现在“按类别选择或排序”主题中,但我已经通读了这些线程,似乎没有任何技巧对我有用。我来了 我的问题你可以在下面看到。我已突出显示了导致我出现问题的查询部分。问题是我想 LocalCurrentAmount不在-1.000000和1.000000之间 不知怎么的。我尝试过CTE版本,但不知何故没有成功,我的declare tables和details视图开始出现问题 非常感谢你的帮助! 贾尼斯 当使用窗口函数时,正如您在文章中所说,您不能在WHERE子句中使用它

我知道窗口函数上有相当多的线程只能出现在“按类别选择或排序”主题中,但我已经通读了这些线程,似乎没有任何技巧对我有用。我来了

我的问题你可以在下面看到。我已突出显示了导致我出现问题的查询部分。问题是我想

LocalCurrentAmount不在-1.000000和1.000000之间

不知怎么的。我尝试过CTE版本,但不知何故没有成功,我的declare tables和details视图开始出现问题

非常感谢你的帮助! 贾尼斯


当使用窗口函数时,正如您在文章中所说,您不能在WHERE子句中使用它。因此,常见的解决方案是使用CTE并在其外部的何处引用它。我用过你的CTE,但是,没有任何样本数据,这完全是猜测。我还为您留下了很多注释,并更改了SQL的其他部分,因为您使用的一些子句将影响查询的性能

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),
Summary AS(
    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) AS 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)) --Why ISNULL for one, COALESCE for the other? Both will make the query non-SARGable
      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]%' --A leading wildcard is going to perform slow
      AND ar.InvoiceDate <= EOMONTH(DATEADD(DAY, -3, GETDATE())) --I have changed this from EOMONTH(GETDATE(), -3 (which made no sense)
      AND NOT EXISTS (SELECT 1
                      FROM @exceptions1 E
                      WHERE E.CustomerCode = cust.CustomerCode) --Changed to EXISTS binned UNION you should use UNION ALL if you're doing something like this, it'll be quicker)
      AND NOT EXISTS (SELECT 1
                      FROM @exceptions2 E
                      WHERE E.CustomerCode = cust.CustomerCode) --Changed to EXISTS binned UNION (you should use UNION ALL if you're doing something like this, it'll be quicker)
      AND NOT EXISTS (SELECT 1
                      FROM @exceptions3 E
                      WHERE E.CustomerCode = cust.CustomerCode)) --Changed to EXISTS binned UNION you should use UNION ALL if you're doing something like this, it'll be quicker)
SELECT *
FROM Summary
WHERE LocalCurrentAmount NOT BETWEEN -1 AND 1
ORDER BY Invoice_date;

值得注意的是,上面的sql完全没有经过测试。我没有访问您的服务器或数据的权限,因此我完全依靠我的眼睛来记录任何错误。

该代码中有很多语法错误。。。例如,您有**ar.OriginalInvoiceAmountOC,稍后为LocalCurrentAmount**。**代表什么?这不是T-SQL语法。还有EOMonthGetDate,-3,其中EOMONTH缺少右括号,EOMONTH只接受1个输入参数。另外,{datetime value}-{int value}是一种非常糟糕的做法,您应该使用DATEADD。嘿,Larnu,我仔细检查了我的代码,LocalCurrentAmount**似乎是一个应对错误,也缺少右括号。但是感谢您指出{datetime value}-{int value},我现在已经将其更正为dateadd!谢谢嗨,拉鲁,谢谢你的回复。我已经测试了代码,并且按照我希望的方式工作。谢谢你的帮助。我将更多地了解你的评论,以帮助我有限的熟练程度提高!非常感谢你的帮助!尽管我改变了主意,并且ar.InvoiceDate@JaanisVeinberg不客气。如果答案为您解决了问题,请不要忘记投票或将其标记为解决方案。投票了吗,但由于我刚刚注册了Stack,由于我的声誉低下,我的评论没有公开显示。@JaanisVeinberg然后将其标记为解决方案,如果它解决了问题。标记解决方案也会给您带来声誉;这对你来说比我更重要。这也意味着,如果其他人有类似的疑问,他们将看到有助于解决问题的答案标记它!再次感谢。
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),
Summary AS(
    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) AS 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)) --Why ISNULL for one, COALESCE for the other? Both will make the query non-SARGable
      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]%' --A leading wildcard is going to perform slow
      AND ar.InvoiceDate <= EOMONTH(DATEADD(DAY, -3, GETDATE())) --I have changed this from EOMONTH(GETDATE(), -3 (which made no sense)
      AND NOT EXISTS (SELECT 1
                      FROM @exceptions1 E
                      WHERE E.CustomerCode = cust.CustomerCode) --Changed to EXISTS binned UNION you should use UNION ALL if you're doing something like this, it'll be quicker)
      AND NOT EXISTS (SELECT 1
                      FROM @exceptions2 E
                      WHERE E.CustomerCode = cust.CustomerCode) --Changed to EXISTS binned UNION (you should use UNION ALL if you're doing something like this, it'll be quicker)
      AND NOT EXISTS (SELECT 1
                      FROM @exceptions3 E
                      WHERE E.CustomerCode = cust.CustomerCode)) --Changed to EXISTS binned UNION you should use UNION ALL if you're doing something like this, it'll be quicker)
SELECT *
FROM Summary
WHERE LocalCurrentAmount NOT BETWEEN -1 AND 1
ORDER BY Invoice_date;