Sql server SQL Server 2005语法帮助-“根据子查询的最大值选择信息”

Sql server SQL Server 2005语法帮助-“根据子查询的最大值选择信息”,sql-server,sql-server-2005,sql-server-2008,sql,Sql Server,Sql Server 2005,Sql Server 2008,Sql,目标在表格列表下方 表: 表:工作 若比德 客户编号 价值 年 表:客户 客户编号 客户名称 表:发票 销售额 客户编号 目标 第1部分:简单我需要选择所有发票记录并按客户排序,以放置漂亮的w/Crystal报告 Select * from Invoice as A inner join Customer as B on A.CustomerID = B.CustomerID 第2部分:现在,我们需要添加两个字段: 与从2008年起具有最大值的客户作业关联的作业ID 与该作业关联的值 伪码 总

目标在表格列表下方

表:

表:工作

若比德 客户编号 价值 年 表:客户

客户编号 客户名称 表:发票

销售额 客户编号 目标

第1部分:简单我需要选择所有发票记录并按客户排序,以放置漂亮的w/Crystal报告

Select * from Invoice as A inner join Customer as B on A.CustomerID = B.CustomerID
第2部分:现在,我们需要添加两个字段:

与从2008年起具有最大值的客户作业关联的作业ID 与该作业关联的值 伪码

总体思路

如果我只与一个特定客户打交道,这是相当容易做到的:

从作业中选择maxJobId、maxValue作为maxJobId,其中Value=从作业中选择maxValue,其中CustomerID=@SpecificCustID和Year='2008'和CustomerID=SpecificCustID和CustomerID='2008'

此子查询确定该客户在2008年的最大值,然后选择一个作业,从2008年起,该客户的潜在多个作业中不能重复具有相同值的作业

困难

当我们没有特定的客户ID进行比较时会发生什么?如果我的目标是选择所有发票记录并按客户排序,则此子查询需要访问它当前处理的客户。我想这可以通过JOIN的ON子句来完成,但这似乎不起作用,因为子查询无法访问它

我显然是疯了。有什么想法吗?

这个函数非常棒,但经常被忽略。您可以在子查询中使用它收回有效作业,如下所示:

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

现在,您已经有了CustomerID和JobID的完整列表,它们满足具有最高JobID的条件,该JobID包含给定年份中该CustomerID的最大值。剩下的就是将它加入到发票和客户中,您就可以开始了。

怎么样。显然,我不能测试,但这里是想法。您需要用您想要选择的内容替换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,这将返回每个会影响性能的客户的最高值。

该函数可以满足您的需要:

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,因此我们可以加入该值。

仅为那些
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

不需要添加CTE。您可以直接加入ROW_NUMBER调用。@肖恩:我认为CTE版本在没有CustomerID的情况下会更有效,但我必须查看执行计划来证明这一点:@我需要建议。。。我得到了3个非常详细的正确答案。我选哪个?如果我必须选一个,我会选肖恩,因为这是最简单的。。。但是我真的不知道哪一个是最有效的。@hamlin:这很简单,运行探查器:我原则上同意子查询比CTE更简单。嗯。。。我是一个新手,使用分析器的经验非常有限。谢谢你的建议。埃里克,谢谢你的详细意见。我现在在玩弄代码。埃里克,你对3个正确答案中哪一个最好有什么建议吗?我们有过解决方案w/CTE,过解决方案w/out CTE和您的解决方案。它们都能工作。@hamlin:对它们进行基准测试。我不知道哪一个比我想象的要快。谁跑得最快,谁就赢了:埃里克。我同意这是一个公平的解决方案。。。但我对分析器的经验不足,无法在一个小时内完成,而且定制基准测试的时间太短。谢谢你的回答。呸,你不必担心剖析器。只需运行查询。速度最快的一回获胜。您还可以查看执行计划,在SSMS的查询编辑器中查看总成本Ctrl+L。Sean,我同意您的答案,因为这是最简单的。就运行时而言。。。我不知道。它们都是很好的解决方案。感谢您的建议。要查找运行时性能:将每个可能的解决方案粘贴到SSM中,然后单击ctrl-L。这将显示估计的执行计划。字段子树成本是在microsoft hq的参考硬件上估计的执行时间(以秒为单位)。小子树成本基因 反弹等于更快。如果不进行测量,我猜这三种解决方案的运行时成本是相似的。
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