SQL:通过连接查找最大值并加入其他值

时间:2016-10-21 13:35:47

标签: sql sql-server

我有一个与客户的“table-a”和一个与客户联系的“table-b”。我想选择每个客户显示上次“通过电话与客户联系”最后一次“客户访问”,以及一些< strong>来自table-b的信息。

表格设计如下:

表一:

number (PK) Name    Adress      
101         Bob     Street 1      
102         Peter   Street 

表-B:

number (PK) c-nr (FK)   type    date        free text
11111       101         visit   01.08.2016  text3     
11112       101         visit   20.08.2016  text2     
11113       102         phone   15.09.2016  text1     
11113       102         email   15.09.2016  text1    

我想查询如下:

Number Name     Adress      Last Visit  Visit Text  Last-Call   Call-Text
101    Bob      Street  1   20.08.2016  text2       NONE        NONE                  
102    Peter    Street  2   NONE        NONE        15.09.206   text1     

到目前为止我得到的是:

select
a.number
,a.name
,a.adress
,last-visit.date
,last-call.date
from table-a as a
left join 
    (select
    inner-b.c-nr as customer-number
    ,max(inner-b.date) as date
    from table-b as inner-b
    where
    type = 'visit'
    group by innner-b.c-nr) as last-visit on last-visit.customer-number = a.number
left join 
    (select
    inner-b.c-nr as customer-number
    ,max(inner-b.date) as date
    from table-b as inner-b
    where
    type = 'phone'
    group by inner-b.c-nr) as last-call on last-call.customer-number = a.number

求助:

它可以显示我最后一次访问和最后一次调用,但我无法达到我可以添加文本的程度,因为如果我添加其他字段(即主键或文本本身) )在内部选择它会搞砸组。此外,我不确定这是“好SQL”。

有什么建议吗?

3 个答案:

答案 0 :(得分:2)

您可以使用OUTER APPLY获取最新的visitphone事件:

SELECT  a.number,
        a.[Name],
        a.Adress,
        CASE WHEN b.[type] = 'visit' THEN b.[date] ELSE NULL END as [Last Visit],
        CASE WHEN b.[type] = 'visit' THEN b.[free text] ELSE NULL END as [Visit Text],
        CASE WHEN c.[type] = 'phone' THEN c.[date] ELSE NULL END as [Last-Call],
        CASE WHEN c.[type] = 'phone' THEN c.[free text] ELSE NULL END as [Call-Text]
FROM tableA a
OUTER APPLY (
    SELECT TOP 1 *
    FROM TableB
    WHERE [c-nr] = a.number and [type] IN ('visit' )
    ORDER BY [date] desc
) b
OUTER APPLY (
    SELECT TOP 1 *
    FROM TableB
    WHERE [c-nr] = a.number and [type] IN ('phone')
    ORDER BY [date] desc
) c

您提供的样本的输出:

number  Name    Adress      Last Visit  Visit Text  Last-Call   Call-Text
101     Bob     Street 1    20.08.2016  text2       NULL        NULL
102     Peter   Street      NULL        NULL        15.09.2016  text1

答案 1 :(得分:1)

你生活中需要row_number:

select a.number, 
       a.name, 
       a.Address,
       b.date as CallDate, 
       b.freetext as CallNotes, 
       c.date as VisitDate, 
       c.freetext as VisitNotes
from TableA a
left join 
    (
        select c_nr, date, freetext, row_number() over(partition by c_nr order by date desc) as Call_Ord
        from TableB
        where type = 'Phone'
    ) b
    on a.number = b.c_nr
    and b.Call_Ord = 1
left join 
    (
        select c_nr, date, freetext, row_number() over(partition by c_nr order by date desc) as Call_Ord
        from TableB
        where type = 'Visit'
    ) c
    on a.number = c.c_nr
    and c.Vis_Ord = 1

答案 2 :(得分:1)

SQL DEMO

WITH lastVisit as (
      SELECT [c-nr], date, [free text],
             row_number() over (partition by [c-nr] order by [date] desc) rn
      FROM table_b
      WHERE type = 'visit'
 ), lastCall as (
      SELECT [c-nr], date, [free text],
             row_number() over (partition by [c-nr] order by [date] desc) rn
      FROM table_b
      WHERE type = 'phone'
 )
 SELECT ta.[number], ta.Name, ta.[Adress],
        COALESCE(lv.date, 'NONE') as [Last Visit],
        COALESCE(lv.[free text], 'NONE') as [Visit Text],

        COALESCE(lc.date, 'NONE') as [Last Call],
        COALESCE(lc.[free text], 'NONE') as [Call Text]

 FROM table_a ta
 LEFT JOIN lastVisit lv
   ON ta.[number] = lv.[c-nr]
  AND lv.rn = 1
 LEFT JOIN lastCall lc
   ON ta.[number] = lc.[c-nr]
  AND lc.rn = 1

<强>输出

enter image description here