Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Difficult select statement assistance

Author  Topic 

James0816
Starting Member

9 Posts

Posted - 2014-02-10 : 08:18:42
I hate doing this, but I'm stumped on writing a particular query. It's probably a case of me just over thinking it but I haven't had a breakthrough on it yet in a few days. Time to call in some more minds.

I have two tables (TableA and TableB). They share similar columns COL1, COL2 and COL3.

Sample Data:
TableA
COL1-----COL2-----COL3
100------OPEN-----01-JAN-2014
101------CLOSE----12-JAN-2014
102------LOCK-----10-JAN-2014
103------CLOSE----12-JAN-2014

TableB
COL1-----COL2-----COL3
100------OPEN-----01-JAN-2014
101------OPEN-----04-JAN-2014
101------LOCK-----05-JAN-2014
101------CLOSE----12-JAN-2014
102------OPEN-----08-JAN-2014
102------LOCK-----10-JAN-2014
103------OPEN-----11-JAN-2014
103------CLOSE----12-JAN-2014

Here's where it gets interesting. I want to capture all records from TableA and select records from TableB meetings this criteria:

- If there is a LOCK record (regardless of other status')
- If there is a CLOSE record BUT no associated LOCK record

Output should look like this:

COL1-----COL2-----COL3
100------OPEN-----01-JAN-2014
101------LOCK-----05-JAN-2014
102------LOCK-----10-JAN-2014
103------CLOSE----12-JAN-2014

I don't have any issues in pulling data matching the first criteria for the LOCKED records. What I am having difficulites with is also pulling the CLOSED records that do not have an associated LOCK with them.

Any coding advice would be greatly appreciated. If you have any further questions or need more info, please let me know.

Thanks kindly,
J.

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2014-02-10 : 08:43:01
[code]
;WIth CTE
AS
(
SELECT *
FROM TableA
UNION ALL
SELECT *
FROM TableB
)
SELECT COL1,COL2,COL3
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY COL1 ORDER BY CASE COL2 WHEN 'LOCK' THEN 0 WHEN 'CLOSE' THEN 1 ELSE 2 END) AS Seq
,*
FROM CTE)t
WHERE Seq=1
[/code]

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/
https://www.facebook.com/VmBlogs
Go to Top of Page

James0816
Starting Member

9 Posts

Posted - 2014-02-10 : 09:02:19
In a word.....HUH? Wow. There was no overthinking that. Would have never came up with that query.

In either case, I copied and pasted it, changed to the real values and it didn't like the statement:

SQL command not properly ended Line 9 Col 1.
Go to Top of Page

ScottPletcher
Aged Yak Warrior

550 Posts

Posted - 2014-02-10 : 17:04:26
I didn't get any errors on that code. But, just in case, here's a different approach that doesn't use CTEs or ROW_NUMBER:



CREATE TABLE TableA (
col1 int,
col2 varchar(10),
col3 date
)
INSERT INTO TableA VALUES(100, 'OPEN', '01-JAN-2014')
INSERT INTO TableA VALUES(101, 'CLOSE', '12-JAN-2014')
INSERT INTO TableA VALUES(102, 'LOCK', '10-JAN-2014')
INSERT INTO TableA VALUES(103, 'CLOSE', '12-JAN-2014')
CREATE TABLE TableB (
col1 int,
col2 varchar(10),
col3 date
)
INSERT INTO TableB VALUES(100, 'OPEN', '01-JAN-2014')
INSERT INTO TableB VALUES(101, 'OPEN', '04-JAN-2014')
INSERT INTO TableB VALUES(101, 'LOCK', '05-JAN-2014')
INSERT INTO TableB VALUES(101, 'CLOSE','12-JAN-2014')
INSERT INTO TableB VALUES(102, 'OPEN', '08-JAN-2014')
INSERT INTO TableB VALUES(102, 'LOCK', '10-JAN-2014')
INSERT INTO TableB VALUES(103, 'OPEN', '11-JAN-2014')
INSERT INTO TableB VALUES(103, 'CLOSE', '12-JAN-2014')
GO


SELECT COL1, CASE WHEN Lock_Date IS NOT NULL THEN 'LOCK' WHEN Close_Date IS NOT NULL THEN 'CLOSE' ELSE 'OPEN' END AS COL2,
COALESCE(Lock_Date, Close_Date, Other_Date) AS COL3
FROM (
SELECT COALESCE(a.COL1, b.COL1) AS COL1,
MAX(CASE WHEN a.Lock_Date > b.Lock_Date THEN a.Lock_Date ELSE b.Lock_Date END) AS Lock_Date,
MAX(CASE WHEN a.Close_Date > b.Close_Date THEN a.Close_Date ELSE b.Close_Date END) AS Close_Date,
MAX(CASE WHEN a.Other_Date > b.Other_Date THEN a.Other_Date ELSE b.Other_Date END) AS Other_Date
FROM (
SELECT
COL1,
MAX(CASE col2 WHEN 'LOCK' THEN COL3 END) AS Lock_Date,
MAX(CASE col2 WHEN 'CLOSE' THEN COL3 END) AS Close_Date,
MAX(COL3) AS Other_Date
FROM TableA
GROUP BY COL1
) AS a
FULL OUTER JOIN (
SELECT
COL1,
MAX(CASE col2 WHEN 'LOCK' THEN COL3 END) AS Lock_Date,
MAX(CASE col2 WHEN 'CLOSE' THEN COL3 END) AS Close_Date,
MAX(COL3) AS Other_Date
FROM TableB
GROUP BY COL1
) AS b ON
b.COl1 = a.COL1
GROUP BY
COALESCE(a.COL1, b.COL1)
) AS derived
ORDER BY COL1

Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2014-02-11 : 00:47:15
quote:
Originally posted by James0816

In a word.....HUH? Wow. There was no overthinking that. Would have never came up with that query.

In either case, I copied and pasted it, changed to the real values and it didn't like the statement:

SQL command not properly ended Line 9 Col 1.


ARe you really using SQL server?
I tested and it works for me.

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/
https://www.facebook.com/VmBlogs
Go to Top of Page

James0816
Starting Member

9 Posts

Posted - 2014-02-11 : 10:53:48
I'm using SQL Developer. Copy and pasted your code, modified for actual data values.

WIth CTE
AS
(SELECT * FROM TableA UNION ALL
SELECT * FROM TableB)
SELECT col1,col2,col3
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY CASE col2 WHEN 'LOCK' THEN 0 WHEN 'CLOSE' THEN 1 ELSE 2 END) AS Seq
,*
FROM CTE)t
WHERE Seq=1;

Error at Line: 7 Column: 1
Go to Top of Page

James0816
Starting Member

9 Posts

Posted - 2014-02-11 : 14:22:29
Let's just back up a bit here if we can. Like I said, I may be over thinking things and might be making it more complicated than it needs to be. I'm going to steer this in a different direction which is probably where I should have started to begin with.


TableA (Master Table) - Contains one record for an event. Status of this record will change depending on what is occuring to it. (I.e. OPEN, LOCK, CLOSE).

TableB (Audit Table) - Contains multiple records for a single event. Every time the status of the record is changed, a record is written to this table. For instance and normal cycle would have (1) record in the Master table to (3) records in the Audit table. (Normal cycle is OPEN, LOCK, CLOSE). There is an exception. A record can go from OPEN to CLOSE.


For this example, I'm only going to focus on CLOSED records. Nothing more, nothing less. So here is my new sample data:


TableA (Has 24 Columns)

COL1 ---------- COL2 ---------- COL3 --------------- COL4 ------------ COL5 ................ rowstamp

100 ------------- CLOSE -------- 01-JAN-2014 ----- FAIL ------------ {some data} ........ 0000001

101 ------------- CLOSE -------- 04-JAN-2014 ----- PASS ---------- {some data} ........ 0000002

102 ------------- CLOSE -------- 12-JAN-2014 ----- PASS ---------- {some data} ........ 0000003

103 ------------- CLOSE -------- 14-JAN-2014 ----- PASS ---------- {some data} ........ 0000004

104 ------------- CLOSE -------- 06-JAN-2014 ----- FAIL ------------ {some data} ........ 0000005

105 ------------- CLOSE -------- 09-JAN-2014 ----- PASS ---------- {some data} ........ 0000006

106 ------------- CLOSE -------- 10-JAN-2014 ----- FAIL ------------ {some data} ........ 0000007

107 ------------- CLOSE -------- 12-JAN-2014 ----- FAIL ------------ {some data} ........ 0000008


TableB (Has 6 Columns)

COL1 ---------- COL2 ---------- COL3 --------------- COL4 ------------ COL5 ------------- rowstamp

100 ------------- OPEN ---------- 30-DEC-2013 ----- {some data} -- {some data} ........ 0000001

100 ------------- LOCK ---------- 30-DEC-2013 ----- {some data} -- {some data} ........ 0000002

100 ------------- CLOSE -------- 01-JAN-2014 ----- {some data} -- {some data} ........ 0000003

101 ------------- OPEN --------- 30-DEC-2014 ----- {some data} -- {some data} ........ 0000004

101 ------------- LOCK ---------- 02-JAN-2014 ----- {some data} -- {some data} ........ 0000005

101 ------------- CLOSE -------- 04-JAN-2014 ----- {some data} -- {some data} ........ 0000006

102 ------------- OPEN ---------- 10-JAN-2014 ----- {some data} -- {some data} ........ 0000007

102 ------------- CLOSE -------- 12-JAN-2014 ----- {some data} -- {some data} ........ 0000008

103 ------------- OPEN ---------- 14-JAN-2014 ----- {some data} -- {some data} ........ 0000009

103 ------------- CLOSE -------- 14-JAN-2014 ----- {some data} -- {some data} ........ 0000010

104 ------------- OPEN ---------- 04-JAN-2014 ----- {some data} -- {some data} ........ 0000011

104 ------------- LOCK ---------- 05-JAN-2014 ----- {some data} -- {some data} ........ 0000012

104 ------------- CLOSE -------- 06-JAN-2014 ----- {some data} -- {some data} ........ 0000013

105 ------------- OPEN ---------- 07-JAN-2014 ----- {some data} -- {some data} ........ 0000014

105 ------------- LOCK ---------- 09-JAN-2014 ----- {some data} -- {some data} ........ 0000015

105 ------------- CLOSE -------- 09-JAN-2014 ----- {some data} -- {some data} ........ 0000016

106 ------------- OPEN ---------- 09-JAN-2014 ----- {some data} -- {some data} ........ 0000017

106 ------------- CLOSE -------- 10-JAN-2014 ----- {some data} -- {some data} ........ 0000018

107 ------------- OPEN ---------- 10-JAN-2014 ----- {some data} -- {some data} ........ 0000019

107 ------------- LOCK ---------- 11-JAN-2014 ----- {some data} -- {some data} ........ 0000020

107 ------------- CLOSE -------- 12-JAN-2014 ----- {some data} -- {some data} ........ 0000021


For my output, I want to track all records from TableA that are in CLOSED status. I want to know when those records were LOCKED. The catch being those records that were CLOSED without first being LOCKED. Therefore that CLOSED status would then be the date I'm looking for.


Output from above data should look like this:

TblA(Col1) .....TblA(Col2) ..... TblB(Col3) ........... TblA(Col4)

100 ------------- CLOSE -------- 30-DEC-2013 ----- FAIL ---> Date record was locked

101 ------------- CLOSE -------- 02-JAN-2014 ----- PASS --> Date record was locked

102 ------------- CLOSE -------- 12-JAN-2014 ----- PASS --> No LOCK date must use CLOSE date

103 ------------- CLOSE -------- 14-JAN-2014 ----- PASS --> No LOCK date must use CLOSE date

104 ------------- CLOSE -------- 05-JAN-2014 ----- FAIL ----> Date record was locked

105 ------------- CLOSE -------- 09-JAN-2014 ----- PASS --> Date record was locked

106 ------------- CLOSE -------- 10-JAN-2014 ----- FAIL ----> No LOCK date must use CLOSE date

107 ------------- CLOSE -------- 11-JAN-2014 ----- FAIL ----> Date record was locked


I hope this scenario clears the air and makes it more understandable of what I am trying to accomplish.


Once again, I greatly appreciate the assist.


Thanks kindly
Go to Top of Page
   

- Advertisement -