处理第一记录子查询的最有效方法

时间:2013-09-09 19:46:09

标签: sql sql-server

我有一张客户ID表和一份客户数据表。客户可以更改ID,但我想查询某些情况下的最早日期,以及其他日期的最新日期。例如,我有两个表:

tbl_a
id        active_id
a         aa
b         aa
c         aa
d         bb
e         bb

tbl_b
id         date      city
a        1/1/2012    Dallas
b        1/1/2013    Houston
c        2/1/2013    Austin
d        1/1/2003    San Antonio
e        3/3/2013    El Paso

tbl_c
id    value
a      50
b      50
b      50
c      50
d      10
e      10
e      10

如何在汇总来自tbl_c的数据时,如何查询数据以返回具有EARLIEST日期和MOST RECENT城市的单个active_id?例如,返回以下内容:

active_id    date      city     sum(value)
aa           1/1/2012  Austin   200 
bb           1/1/2003  El Paso  30

在语义方面,我试图找出任何active_id的第一个日期和最近的城市,同时总结交易价值。

3 个答案:

答案 0 :(得分:2)

如果您可以使用窗口函数(并且无法访问first_value函数):

with cte as (
    select
        row_number() over(partition by a.active_id order by b.date asc) as rn1,
        row_number() over(partition by a.active_id order by b.date desc) as rn2,
        a.active_id, b.date, b.city
    from tbl_a as a
        inner join tbl_b as b on b.id = a.id
)
select
    c.active_id,
    c1.date,
    c2.city
from (select distinct active_id from cte) as c
    left outer join cte as c1 on c1.active_id = c.active_id and c1.rn1 = 1
    left outer join cte as c2 on c2.active_id = c.active_id and c2.rn2 = 1

<强> sql fiddle demo

如果您可以使用first_value功能:

with cte as (
    select
        first_value(b.date) over(partition by a.active_id order by b.date asc) as date,
        first_value(b.city) over(partition by a.active_id order by b.date desc) as city,
        a.active_id
    from tbl_a as a
        inner join tbl_b as b on b.id = a.id
)
select distinct
    active_id, date, city
from cte

答案 1 :(得分:1)

尝试这样的事情:

;WITH DATA 
     AS (SELECT T1.ACTIVE_ID, 
                T2.* 
         FROM   TABLEA T1 
                INNER JOIN TABLEB T2 
                        ON T1.ID = T2.ID), 
     DATA2 
     AS (SELECT T1.ACTIVE_ID, 
                SUM(T2.VALUE) TOT_VALUE 
         FROM   TABLEA T1 
                INNER JOIN TABLEC T2 
                        ON T1.ID = T2.ID 
         GROUP  BY ACTIVE_ID) 
SELECT T3.ACTIVE_ID, 
       DATE, 
       CITY, 
       T5.TOT_VALUE AS [SUM(VALUE)] 
FROM   DATA T3 
       INNER JOIN (SELECT MIN(DATE) MAXDATE, 
                          ACTIVE_ID 
                   FROM   DATA 
                   GROUP  BY ACTIVE_ID)T4 
               ON T3.ACTIVE_ID = T4.ACTIVE_ID 
                  AND T3.DATE = T4.MAXDATE 
       INNER JOIN DATA2 T5 
               ON T3.ACTIVE_ID = T5.ACTIVE_ID 

可以在 SQL Fiddle 找到一个工作示例。

祝你好运!

答案 2 :(得分:1)

这假定tbl_a <--> tbl_b为1 - 1

tran_sum可以像max(tran_sum)一样放在这里,也可以通过

添加到群组中
Select
    active_id,
    max(case r1 when 1 then date end) date,
    max(case r2 when 1 then city end) city,
    max(tran_sum)
From (
    Select
        a.active_id,
        sum(c.value) over (partition by a.active_id) tran_sum,
        row_number() over (partition by a.active_id order by date) as r1,
        b.date,
        row_number() over (partition by a.active_id order by date desc) as r2,
        b.city
    From
        tbl_a a
            inner join
        tbl_b b
            on a.id = b.id
            inner join
        tbl_c c
            on a.id = c.id
    ) x
Group By
    active_id;