简体   繁体   中英

SQL Query Table for Changes to record based on previous record (SQL Server)

Apologies for my impending question, but I'm probably a bit over my head here... SQL was not something I was trained in, and it's been a learn-as-you-go endeavor. I am trying to query an existing single table in SQL Server 2008 ( in Compatibility mode for SQL Server 2000 ).

The table structure as similar to the following:

Table1
+----------+----------+----------+---------+---------+---------+------------+---------+
|   Date   | RecordID | Revision | AttribA | AttribB | AttribC |  AttribD   | AttribE |
+----------+----------+----------+---------+---------+---------+------------+---------+
| 1/1/2014 |        1 |        0 | mammal  | horse   | slimy   | tasty      | Grade 4 |
| 1/1/2014 |        1 |        1 | mammal  | dog     | slimy   | tasty      | Grade 3 |
| 1/1/2014 |        1 |        2 | mammal  | dog     | soft    | tasty      | Grade 2 |
| 1/1/2014 |        1 |        3 | mammal  | dog     | soft    | lick       | Grade 2 |
| 1/1/2014 |        2 |        0 | puppet  | sock    | soft    | less tasty | Grade 9 |
| 1/1/2014 |        2 |        1 | puppet  | sock    | soft    | not tasty  | Grade 9 |
+----------+----------+----------+---------+---------+---------+------------+---------+

RecordID and RevisionNum are Primary Keys . There may be multiple revisions of a single RecordID stored in the Table1 as a form of Audit History.

In addition, let's say AttributeA & AttributeB are unofficially related as Group A, AttributeC & AttributeD are related as Group B, and AttributeE is on its own as Group C.

My task is to write a query that, given a RecordID , will return the following:

+----------+----------+----------+---------+---------+---------+
|   Date   | RecordID | Revision | Group A | Group B | Group C |
+----------+----------+----------+---------+---------+---------+
| 1/1/2014 |        1 |        0 |         |         |         |
| 1/1/2014 |        1 |        1 |    X    |         |     X   |
| 1/1/2014 |        1 |        2 |         |    X    |     X   |
| 1/1/2014 |        1 |        3 |         |    X    |         |
+----------+----------+----------+---------+---------+---------+

Where the query returns an entry for each revision for a single record with 'X' if any column in the "Group" was updated from the previous value.

So far my best attempt has been to set:

DECLARE  @ID   INTEGER
DECLARE  @Revision  INTEGER
SET @ID = 1
SET @Revision = 3
...
  SET @GroupA = (SELECT COUNT(*) FROM
   (SELECT DISTINCT AttribA, AttribB
    FROM [dbo].[Table1]
    WHERE RecordID = @ID 
      AND RevisionID in (@Revision ,@Revision -1)) A)
... 
SELECT @ID
      ,[RevisionID]
      ,[Date]
      ,[GroupA] =
        CASE 
          WHEN @GroupA = 1 THEN ''
          ELSE 'X'
        END
...
  FROM [dbo].[Table1]
  WHERE RecordID = @ID
    AND RevisionID = @Revision

I've cut out some duplicate code to show you the general strategy, but I honestly think it's a complete mess that I doubt I'll be able to remedy without turning it into a nightmare. Could anyone give me a tip on how they might better complete the task described in SQL Server 2000 compatibility? I appreciate any assistance here.

try below sql:

UPDATED change the inner join to left join. ;)

select a.RecordId,a.Revision
    , Case When a.AttribA +' '+a.AttribB <> ab.[Group A] then 'X' else '' End as 'Group A'
    , Case When a.AttribC +' '+a.AttribD <> ab.[Group B] then 'X' else '' End as 'Group B'
    , Case When a.AttribE <> ab.[Group C] then 'X' else '' End as 'Group C'
    , a.AttribA +' '+a.AttribB as 'Group A'
    , a.AttribC+ ' ' + a.AttribD as 'Group B'
    , a.AttribE as 'Group C'
    , ab.[Group A] as 'PrevRevision A'
    , ab.[Group B] as 'PrevRevision B'
    , ab.[Group C] as 'PrevRevision C'
from @tempData a
left join
(
    select b.RecordId,b.Revision
    , b.AttribA +' '+b.AttribB as 'Group A'
    , b.AttribC+ ' ' + b.AttribD as 'Group B'
    , b.AttribE as 'Group C'
    from @tempData b

) ab on a.RecordId=ab.RecordId and a.Revision = ab.Revision + 1

order by a.RecordId, a.Revision

Result Data:

RecordId    Revision    Group A Group B Group C Group A       Group B         Group C  PrevRevision A   PrevRevision B   PrevRevision C
----------- ----------- ------- ------- ------- ------------- --------------- -------- ---------------- ---------------- --------------- 
1           0                                   mammal horse  slimy tasty     Grade 4  NULL             NULL             NULL
1           1           X               X       mammal dog    slimy tasty     Grade 3  mammal horse     slimy tasty      Grade 4
1           2                   X       X       mammal dog    soft tasty      Grade 2  mammal dog       slimy tasty      Grade 3
1           3                   X               mammal dog    soft lick       Grade 2  mammal dog       soft tasty       Grade 2
2           0                                   puppet sock   soft less tasty Grade 9  NULL             NULL             NULL
2           1                   X               puppet sock   soft not tasty  Grade 9  puppet sock      soft less tasty  Grade 9

I don't know the limitations of SQL Server 2000, but perhaps this approach would work:

select 
  RecordID,
  Revision, 
  AttribA,
  AttribB,
  ( select 'X' 
    from t1 as B
    where B.RecordID = A.RecordID
    and   B.Revision = A.revision - 1
    and  (B.AttribA <> A.AttribA or B.AttribB <> A.AttribB)
  ) AS GroupA
from t1 as A
where RecordID = 1
;

Here is a fiddle which shows it running: http://sqlfiddle.com/#!3/b4626e/6

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM