用于显示列中子记录的重复数据的SQL查询

时间:2012-11-26 13:24:30

标签: sql-server-2000 pivot duplicate-data

我在SQL Server 2000数据库中有以下表格:

MasterID | Details   | [other fields]
=====================================
PK (int) | Free text | ...

LogTable

LogID    | MasterID | UserID    | LogDate    | LogText
==========================================================
PK (int) | FK (int) | VarChar(2)| Date stamp | Free text

每个主记录可能有许多日志条目。

我有一个查询,它为每个主行提取最近的三个相关日志条目,如下所示。请注意,执行适当的转换和格式化以实现LogData连接(为清晰起见省略):

SELECT 
    M.MasterID, M.Details, L.LogDate + L.UserID + L.LogText AS LogData 
FROM
    MasterTable M 
INNER JOIN 
    LogTable L ON M.MasterID = L.MasterID 
    AND L.LogID IN (SELECT TOP 3 LogID FROM LogTable 
                    WHERE MasterID = M. MasterID ORDER BY LogDate DESC)

这会产生如下输出:

MasterID | Details | LogData
========================================================
1        | First   | 05/11/2012 AB Called Client  
2        | Second  | 08/11/2012 CD Client Visit  
2        | Second  | 07/11/2012 CD Called Client  
2        | Second  | 05/11/2012 AB Called Client  

我需要实现的是将第二个表中的数据显示为输出中的列,所有数据都针对每个主记录进行报告,从而避免重复数据。像这样:

MasterID | Details | LogData1                    | LogData2                    | LogData3
===========================================================================================================
1        | First   | 05/11/2012 AB Called Client | (null)                      | (null)  
2        | Second  | 08/11/2012 CD Client Visit  | 07/11/2012 CD Called Client | 05/11/2012 AB Called Client  

请注意,在实际需求中,此解决方案将是展平5个表的一部分,其输出包含大约20,000行和90列数据。

提前致谢。

1 个答案:

答案 0 :(得分:1)

我要发布这个,只是为了表明它可以完成,但是非常抱怨,而不是通过SQL来实现。应该通过在列上显示更加动态的UI来完成。即使这样,我也会以不同的方式设计它。

-- create master table
DECLARE @MasterTable TABLE (
    [MasterID] [int] IDENTITY (1, 1) NOT NULL ,
    [Details] [varchar] (50) ,
    [AdditionalField_1] [varchar] (50) ,
    [AdditionalField_n] [varchar] (50) 
)
-- create log table
DECLARE @LogTable TABLE (
    [LogID] [int] IDENTITY (1, 1) NOT NULL ,
    [MasterID] [int] NULL ,
    [UserID] [varchar] (2) ,
    [LogDate] [datetime] NULL ,
    [LogText] [varchar] (50) 
) 
-- insert into master table
INSERT INTO @MasterTable  (Details)
        VALUES ('First')
INSERT INTO @MasterTable  (Details)
        VALUES ('Second') 
-- insert into log table
INSERT INTO @LogTable  (MasterID, UserID, LogDate, LogText)
        VALUES (1, 'AB', '05/11/2012', 'Called Client')   
INSERT INTO @LogTable  (MasterID, UserID, LogDate, LogText)
        VALUES (2, 'AB', '05/11/2012', 'Called Client')   
INSERT INTO @LogTable  (MasterID, UserID, LogDate, LogText)
        VALUES (2, 'CD', '07/11/2012', 'Called Client')   
INSERT INTO @LogTable  (MasterID, UserID, LogDate, LogText)
        VALUES (2, 'CD', '08/11/2012', 'Client Visit') 
-- create table to display data
DECLARE @MyTemp TABLE (MasterID INT, Details VARCHAR(50), LogData1 VARCHAR(50), LogData2 VARCHAR(50), LogData3 VARCHAR(50))
INSERT INTO @MyTemp SELECT MasterID, Details, NULL, NULL, NULL FROM @MasterTable
-- create vars
DECLARE @ID INT, @NewID INT, @MasterID INT, @NewValue VARCHAR(100)
SET @ID = 0
-- loop through data
WHILE @ID >-1
BEGIN
    -- clear vars
    SELECT @NewID = NULL, @MasterID = NULL, @NewValue = NULL
    -- get first record
    SELECT TOP 1    
        @NewValue = CONVERT(VARCHAR(10), LogDate, 103)+ ' ' + UserID + ': ' + LogText
    ,   @MasterID=MasterID
    ,   @NewID=LogID 
    FROM @LogTable WHERE LogID>@ID
    -- if no data, exit loop
    IF @NewID IS NULL
        BREAK
    -- update record based on valuds in fields
    UPDATE m 
        SET @ID = @NewID
        ,   LogData1 = (CASE WHEN m.LogData1 IS NULL THEN @NewValue ELSE m.LogData1 END)
        ,   LogData2 = (CASE WHEN m.LogData1 IS NOT NULL THEN 
                            (CASE WHEN m.LogData2 IS NULL THEN @NewValue ELSE m.LogData2 END)
                        ELSE m.LogData2 END)
        ,   LogData3 = (CASE WHEN m.LogData1 IS NOT NULL THEN 
                            (CASE WHEN m.LogData2 IS NOT NULL THEN 
                                (CASE WHEN m.LogData3 IS NULL THEN @NewValue ELSE m.LogData3 END)
                             ELSE m.LogData3 END)
                        ELSE m.LogData3 END)
    FROM @MyTemp m
    WHERE m.MasterID=@MasterID
END
--display all data
SELECT * FROM @MyTemp