2011-11-30 48 views
0

我不知道,标题是非常描述性的,但这里的问题,选择一个基于MAX(关键)数据...如何不进行分组

有没有一种方法来选择基于数据列Max键值,跨多个表连接。请考虑:

Table A 
------- 
PK1 
PK2 
PK3 
PK4 
dataColumn 
... data 

Table B 
------- 
PK1 
PK2 
PK3 
... data 

Table C 
------- 
PK1 
PK2 
PK3 
PK4 
... data 

SELECT A.dataColumn, A.PK1, A.PK2, MAX(A.PK3), A.PK4 
FROM A a INNER JOIN B b ON a.PK1 = b.PK1 AND a.PK2 = b.PK2 AND a.PK3 = b.PK3 
     INNER JOIN C c ON a.PK1 = c.PK1 AND a.PK2 = c.PK2 AND a.PK3 = c.PK3 AND a.PK4 = c.PK4 
GROUP BY A.PK1, A.PK2, A.PK4 -- I do not want to add in A.dataColumn 

的问题是,为了得到MAX(A.PK3),我也必须由数据,这组我不想要的。 A.PK1,A.PK2,A.PK4和MAX(A.PK3)唯一地定义了我想要的行。通过在组中添加,我将得到每个A.dataColumn的MAX(A.PK3),这不是我想要的。基本上,A.PK3是一个日期时间字段;我想要基于其他键的最新时间的数据。其他键唯一标识一些设备,时间是错误的时间,然后数据是错误信息(非常简化)。我想要指定PK1,PK2和PK4的最新错误信息。

目前,我们分成两个,几乎相同的查询,并加入他们的行列为:

SELECT j.PK1, j.PK2, j.PK3, j.PK4, k.dataColumn 
FROM A a 
INNER JOIN 
(
    SELECT A.PK1, A.PK2, MAX(A.PK3), A.PK4 -- no data column selected 
    FROM A a INNER JOIN B b ON a.PK1 = b.PK1 AND a.PK2 = b.PK2 AND a.PK3 = b.PK3 
      INNER JOIN C c ON a.PK1 = c.PK1 AND a.PK2 = c.PK2 AND a.PK3 = c.PK3 AND a.PK4 = c.PK4 
    GROUP BY A.PK1, A.PK2, A.PK4 
) j 
ON a.PK1 = j.PK1 AND a.PK2 = j.PK2 AND a.PK3 = j.PK3 AND a.PK4 = j.PK4 
INNER JOIN 
(
    SELECT A.dataColumn, A.PK1, A.PK2, A.PK3, A.PK4 -- data column, but no MAX 
    FROM A a INNER JOIN B b ON a.PK1 = b.PK1 AND a.PK2 = b.PK2 AND a.PK3 = b.PK3 
      INNER JOIN C c ON a.PK1 = c.PK1 AND a.PK2 = c.PK2 AND a.PK3 = c.PK3 AND a.PK4 = c.PK4 
) k 
ON j.PK1 = k.PK1 AND j.PK2 = k.PK2 AND j.PK3 = k.PK3 AND j.PK4 = k.PK4 

所以,你可以看到,第一INNER JOIN得到的PK,而不是数据,那么第二个连接从第一个内部联接中的PK获取数据。这似乎是可怕的!这个例子过于简化,但在我们的例子中,我们加入的表包含数百万条记录,并且每个JOIN中的操作几乎相同。

任何帮助删除内部联接之一将是真棒和赞赏!

回答

3

一个选项,在SQL 2005和起来,就是用的“排行榜”功能中的一个,像这样:

SELECT SubQuery.dataColumn, SubQuery.PK1, SubQuery.PK2, SubQuery.A.PK3, SubQuery.PK4 
FROM (SELECT A.dataColumn, A.PK1, A.PK2, A.PK3, A.PK4 
     ,row_number() over (partition by A.PK1, A.PK2, A.PK4 order by A.PK3 desc) Ranking 
     FROM A a INNER JOIN B b ON a.PK1 = b.PK1 AND a.PK2 = b.PK2 AND a.PK3 = b.PK3 
       INNER JOIN C c ON a.PK1 = c.PK1 AND a.PK2 = c.PK2 AND a.PK3 = c.PK3 AND a.PK4 = c.PK4 
     GROUP BY A.PK1, A.PK2, A.PK4) SubQuery 
WHERE SubQuery.Ranking = 1 

最佳详细解释books online。注意事项:我无法测试上述代码,可能存在拼写错误或小错误。而且,虽然逻辑上合理,但性能可能不佳,因此需要测试性能是否足够。

+0

太棒了,谢谢。我将对此进行测试,并发布如何执行这一操作,而不是按照指示分割查询。 – MPavlak