压缩重复数据,同时为每个客户端维护多个条目

时间:2016-04-06 12:54:01

标签: sql sql-server duplicates

如果标题不够具有描述性,我道歉。我很难描述我在寻找什么。

我知道这通常是在前端完成的,但是客户端要求以这种方式显示这些数据。这应该显示一个包含客户信息(姓氏,名字)和任何/所有预约约会的列。由于每个客户可能有多个约会,因此每行会显示重复数据。这将是这样的:

lastName | firstName | apptDate | myStartTime | myEndTime

史密斯.............. |约翰................ | 2016年4月7日........ | 7:00 ......................... | 8:00

史密斯.............. |约翰................ | 2016年4月9日........ | 6:00 ......................... | 7点

史密斯.............. |约翰................ | 2016年4月14日...... | 10:00 ....................... | 11:00

阿诺德............. |威廉姆斯.......... | 2016年4月10日...... | 7:00 ......................... | 11:00

阿诺德............. |威廉姆斯.......... | 2016年4月11日...... | 8:00 ......................... | 12:00

但我希望将其显示为:

史密斯.............. |约翰................ | 2016年4月7日........ | 7:00 ......................... | 8:00

............................................... 。| 2016年4月9日........ | 6:00 ......................... | 7点

............................................... 。| 2016年4月14日...... | 10:00 ....................... | 11:00

阿诺德.............. |威廉姆斯......... | 2016年4月10日....... | 7:00 ......................... | 11:00

............................................... 。| 2016年4月11日....... | 8:00 ......................... | 12:00

这就是我目前正在使用的内容:

SELECT
    CASE
        WHEN cli.rownum = 1 THEN cli.clientID    
    END                                                       AS 'clientID' 
    ,CASE 
        WHEN cli.rownum = 1 THEN cli.lastName 
    END                                                       AS 'lastName'
    ,CASE 
        WHEN cli.rownum = 1 THEN cli.firstName 
    END                                                       AS 'firstName'
    ,CASE
        WHEN cli.rownum = 1 THEN cli.homePhone                
    END                                                       AS 'home'
    ,CASE
        WHEN cli.rownum = 1 THEN cli.cellPhone                
    END                                                       AS 'cell'
    ,info.*
    ,CASE
        WHEN cli.rownum = 1 THEN cli.staffAlertMsg            
    END                                                       AS 'alert'   
    ,cli.notes                                                AS 'notes' 
    ,CONVERT(varchar(10),cli.classDate,101)                   AS 'date'
    ,cli.myStartTime                                          AS 'start'
    ,cli.myEndTime                                            AS 'end'
    ,cli.typeName                                             AS 'appointment'
FROM 
(SELECT
    c.clientID
    ,c.lastName
    ,c.firstName
    ,c.homePhone
    ,c.cellPhone
    ,info.*
    ,r.notes
    ,c.staffAlertMsg  
    ,r.ClassDate
    ,r.myStartTime
    ,r.myEndTime
    ,vt.TypeName
    ,ROW_NUMBER() 
        OVER(PARTITION BY c.clientID ORDER BY c.clientID) AS 'rownum'
FROM clients c
    LEFT OUTER JOIN tblReservation r
        ON c.clientID = r.clientID
    LEFT OUTER JOIN tblVisitTypes vt
        ON vt.TypeID = r.visitType
    OUTER APPLY
    (SELECT
            max(CASE
                WHEN civ.clientIndexID = 4 
                    THEN civ.clientIndexValueName
            END)                                 AS 'priority'
            ,max(CASE
                WHEN civ.clientIndexID = 5 
                    THEN civ.clientIndexValueName
            END)                                 AS 'lang'
            ,max(CASE
                WHEN civ.clientIndexID = 17 
                    THEN civ.clientIndexValueName
            END)                                 AS 'inter'
            ,max(CASE
                WHEN ccf.name LIKE 'prac'
                    THEN ccv.TextVal
            END)                                 AS 'prac'
            ,max(CASE
                WHEN st.TypeID = 100000001 THEN st.typeName
            END)                                 AS 'ride?'
            ,max(CASE
                WHEN st.typeID = 100000006 THEN st.typeName
            END)                                 AS 'l?'
            FROM tblClientCustomValues ccv
                INNER JOIN tblClientCustomFields ccf
                    ON ccv.ID = ccf.ID
                INNER JOIN tblClientIndexData cid
                    ON ccv.clientID = cid.clientID
                INNER JOIN tblClientIndexValue civ
                    ON cid.clientIndexValueID = civ.clientIndexValueID
                LEFT JOIN [type details] td
                    ON ccv.clientID = td.clientID
                LEFT JOIN [student types] st
                    ON td.typeID = st.typeID
         WHERE c.clientID = ccv.clientID
    ) info
) cli

WHERE cli.clientID != '-2' 
    AND cli.clientID != '0' 
    AND cli.clientID != '1' 
    AND (cli.classDate >= '4/1/2016' 
    AND cli.classDate <= '4/30/2016')

1 个答案:

答案 0 :(得分:0)

假设您只想返回每个客户端第一行的名称,那么这应该有效(同样假设ID表上的主键列为clients):

SELECT CASE WHEN cli.rownum = 1 THEN cli.lastName END AS lastName
,CASE WHEN cli.rownum = 1 THEN cli.firstName END AS firstName
,CONVERT(varchar(10),cli.apptDate,101) AS 'apptDate'
,cli.myStartTime
,cli.myEndTime

FROM 

(SELECT c.ID
    ,c.lastName
    ,c.firstName
    ,r.apptDate
    ,r.myStartTime
    ,r.myEndTime
    ,ROW_NUMBER() OVER (PARTITION BY c.ID ORDER BY c.ID, r.apptDate, r.myStartTime) as rownum

    FROM clients c
    LEFT OUTER JOIN tblReservation r
    ON c.clientID = r.clientID
    LEFT OUTER JOIN tblVisitTypes vt
    ON vt.TypeID = r.VisitType) 
cli

ORDER BY cli.ID, cli.rownum

我已经同时加入LEFT OUTER JOINS,因为您的第二个INNER JOIN会使第一个加入INNER,我认为这不是您想要的。