繁体   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