扁平化特定用户的电子邮件链数据和最小发送日期Sql Server

时间:2016-01-05 02:01:08

标签: sql sql-server tsql

如何编写查询以返回发送给特定人员的电子邮件的最早记录,并将结果展平。

例如,我有一个特定于ID的电子邮件链:

ID   SENTTO  Date
A1   23      1/1/2015
A1   23      1/3/2015
A1   24      1/5/2015
A2   23      1/3/2015
A2   24      1/4/2015
A2   23      1/5/2015
A3   24      1/1/2015
A3   24      1/3/2015

结果:

ID   SENTTO23 Min(Date) SENTTO24 MIN(DATE)
A1   23       1/1/2015  24       1/5/2015
A2   23       1/3/2015  24       1/4/2015
A3   NULL     NULL      24       1/1/2015

我写的代码如下:

SELECT ID, MIN(DATE)
FROM TABLEA
LEFT JOIN TABLEB AS TB1 ON TABLEAID=TABLEBID
LEFT JOIN TABLEB AS TB2 ON TABLEAID=TABLEB2ID
WHERE (TB1.SENTTO = 23 OR TB1.SENTTO IS NULL)
AND (TB2.SENTTO = 24 OR TB2.SENTTO IS NULL)

但我得到类似这样的东西,它既可以抓住任何日期,也可以只抓取包含两个日期的记录:

ID   SENTTO23 Min(Date) SENTTO24 MIN(DATE)
A1   23       1/1/2015  24       1/5/2015
A2   23       1/3/2015  24       1/4/2015
A3   24       1/1/2015  24       1/1/2015

1 个答案:

答案 0 :(得分:0)

首先,您希望得到每个MIN(DATE) GROUP BY ID, SENTTO。您可以使用此查询:

SELECT
    ID, SENTTO, MinDate = MIN(Date)
FROM tbl
GROUP BY ID, SENTTO
ORDER BY ID, SENTTO

这会给你:

ID   SENTTO      MinDate
---- ----------- ----------
A1   23          2015-01-01
A1   24          2015-01-05
A2   23          2015-01-03
A2   24          2015-01-04
A3   24          2015-01-01

现在您已拥有MIN(DATE),您可以将上述结果用于PIVOT数据。以下是使用动态交叉表的一种方法:

DECLARE @sql NVARCHAR(MAX) = N''
SELECT @sql = 
'SELECT
    ID' + CHAR(10)

SELECT @sql = @sql +
'   , MAX(CASE WHEN SENTTO = ' + CONVERT(VARCHAR(10), SENTTO) + ' THEN SENTTO END) AS ' + QUOTENAME('SENTTO'+ CONVERT(VARCHAR(10), SENTTO)) + CHAR(10) +
'   , MAX(CASE WHEN SENTTO = ' + CONVERT(VARCHAR(10), SENTTO) + ' THEN MinDate END) AS ' + QUOTENAME('MIN(DATE)') + CHAR(10)
FROM(
    SELECT DISTINCT SENTTO FROM Tbl
) t

SELECT @sql = @sql +
'FROM(
    SELECT
        ID, SENTTO, MinDate = MIN(Date)
    FROM tbl
    GROUP BY ID, SENTTO
)t
GROUP BY ID
ORDER BY ID'

PRINT @sql
EXEC (@sql)

SQL Fiddle