[英]SQL Server 2005 Syntax Help - “Select Info based upon Max Value of Sub Query”
目標在表格列表下方。
表:
表:工作
表:客戶
表:發票
目標
第1部分:(簡單)我需要選擇所有發票記錄並按客戶排序(以放置帶有Crystal Reports的頁面)
Select * from Invoice as A inner join Customer as B on A.CustomerID = B.CustomerID
第2部分:(困難)現在,我們需要添加兩個字段:
偽代碼
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'
您會看到,這將拉回所有作業,但帶有附加的列,您可以了解每個客戶的最大價值。 在下一個子查詢中,我們過濾出所有value
和maxVal
相等的行。 此外,它會根據customerid
和maxVal
查找最大JobID
,因為我們只需要拉回一個JobID
和一個JobID
(根據要求)。
現在,你有一個完整列表CustomerID
和JobID
,以滿足具有最高條件JobID
包含的最大Value
為CustomerID
在某一年。 剩下的就是將它加入到Invoice
和Customer
,您就很好了。
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.