簡體   English   中英

SQL Server 2005語法幫助-“基於子查詢的最大值選擇信息”

[英]SQL Server 2005 Syntax Help - “Select Info based upon Max Value of Sub Query”

目標在表格列表下方。

表:

表:工作

  • 作業ID
  • 顧客ID

表:客戶

  • 顧客ID
  • 的CustName

表:發票

  • SaleAmount
  • 顧客ID

目標

第1部分:(簡單)我需要選擇所有發票記錄並按客戶排序(以放置帶有Crystal Reports的頁面)

Select * from Invoice as A inner join Customer as B on A.CustomerID = B.CustomerID

第2部分:(困難)現在,我們需要添加兩個字段:

  • 與具有最大值的該客戶的作業關聯的JobID(自2008年起)
  • 與該工作相關的價值

偽代碼

Select * from 
Invoice as A
inner join Customer as B on A.CustomerID = B.CustomerID
inner join 
(select JobID, Value from Jobs where Job:JobID has the highest value out of all of THIS customer's jobs from 2008) 

一般思想

  • 如果我只與一個特定的客戶打交道,這很容易做到:

    從Jobs中選擇max(JobId),max(Value)作為MaxJobID,其中Value =(從CustomerID = @SpecificCustID並且Year ='2008'的Jobs中選擇max(Value)),並且CustomerID = SpecificCustID和CustomerID ='2008'

該子查詢確定該客戶在2008年的最大價值,然后從該客戶具有相同價值的2008年以來的多個潛在工作中選擇一個工作(不能重復)。

難點

當我們沒有可比較的特定客戶ID時會發生什么? 如果我的目標是選擇所有發票記錄並按客戶排序,則此子查詢需要訪問當前正在處理的客戶。 我想這可以通過JOIN的ON子句“完成”,但實際上似乎不起作用,因為子子查詢無法訪問它。

我顯然在頭上。 有什么想法嗎?

如何使用CTE 顯然,我無法測試,但這是個主意。 您需要用要選擇的內容替換col1,col2,...,coln。

Inv( col1, col2, ... coln)
AS
(
  SELECT col1, col2, ... coln,
     ROW_NUMBER() OVER (PARTITION BY A.CustomerID 
     ORDER BY A.Value DESC) AS [RowNumber]
      FROM Invoice A INNER JOIN Customer B ON A.CustomerID = B.CustomerID
      WHERE A.CustomerID = @CustomerID
      AND A.Year = @Year
)
SELECT * FROM Inv WHERE RowNumber = 1

如果您沒有CustomerID,這將返回每個客戶的最高價值(這會損害性能)。

over函數是一個很棒的功能,但是經常被忽略。 您可以在子查詢中使用它來拉回有效的作業,如下所示:

select
    a.*
from
    invoice a
    inner join customer b on
        a.customerid = b.customerid
    inner join (select customerid, max(jobid) as jobid, maxVal from
               (select customerid, 
                jobid,
                value,
                max(value) over (partition by customerid) as maxVal
                from jobs
                where Year = '2008') s
               where s.value = s.maxVal
               group by customerid, maxVal) c on
        b.customerid = c.customerid
        and a.jobid = c.jobid

本質上,第一個內部查詢如下所示:

select 
    customerid, 
    jobid,
    value,
    max(value) over (partition by customerid) as maxVal
from jobs
where Year = '2008'

您會看到,這將拉回所有作業,但帶有附加的列,您可以了解每個客戶的最大價值。 在下一個子查詢中,我們過濾出所有valuemaxVal相等的行。 此外,它會根據customeridmaxVal查找最大JobID ,因為我們只需要拉回一個JobID和一個JobID (根據要求)。

現在,你有一個完整列表CustomerIDJobID ,以滿足具有最高條件JobID包含的最大ValueCustomerID在某一年。 剩下的就是將它加入到InvoiceCustomer ,您就很好了。

row_number()函數可以為您提供所需的信息:

Select A.*, B.*, C.JobID, C.Value
from 
Invoice as A
inner join Customer as B on A.CustomerID = B.CustomerID
inner join (
   select JobID, Value, CustomerID,
   ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY Value DESC) AS Ordinal
   from Jobs
   WHERE Year = 2008
) AS C ON (A.CustomerID = C.customerID AND C.Ordinal = 1)

此查詢中的ROW_NUMBER()函數將按值降序排列,而PARTITION BY子句將分別為CustomerID的每個不同值執行此操作。 這意味着每個客戶的最高價值將始終為1,因此我們可以加入該價值。

只是為了配合用於<MSSQL 2005的non row_number解決方案。個人而言,我發現更容易遵循myslef ...但是考慮到我在MSSQL 2000和2005+上花費了多少時間,這可能會有所偏差。

SELECT * 
FROM Invoice as A
INNER JOIN Customer as B ON
    A.CustomerID = B.CustomerID
INNER JOIN (
    SELECT
       CustomerId,
       --MAX in case dupe Values. 
       ==If UC on CustomerId, Value (or CustomerId, Year, Value) then not needed
       MAX(JobId) as JobId 
    FROM Jobs
    JOIN (
        SELECT
            CustomerId,
            MAX(Value) as MaxValue
        FROM Jobs
        WHERE Year = 2008
        GROUP BY
            CustomerId
    ) as MaxValue ON
         Jobs.CustomerId = MaxValue.CustomerId
         AND Jobs.Value = MaxValue.MaxValue
    WHERE Year = 2008
    GROUP BY
         CustomerId
) as C ON
     B.CustomerID = C.CustomerID

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM