| Author |
Topic |
|
A.J.Gibson
Starting Member
9 Posts |
Posted - 2009-06-30 : 17:27:23
|
| I'm trying to figure out how to join a table to itself with some very weird criteria, and I would appreciate any insight into how it could be done.Basically, each row in the table can be of one of two possible types and has a timestamp, and I need to create a resulting table such that each member of the first type is joined to the member of second type that occurs after it chronologically after it, and only that one instance. If the first type has an extra hanging off the end, it should be given a null for it's second time (he assumption being the second thing hasn't happened yet). We can assume that data is going to be generally pairable in this way (there can't be a second X until there has been a Y), with the exception being the afford mentioned first type with second type having not happened yet. There may be a junk second type at the beginning, which can be ignored.Confused? Here is my example:Before:Type: Time:Y 0X 3Y 7X 8Y 9X 11Y 17X 20After:Type1: Time1: Type2: Time2:X 3 Y 7X 8 Y 9X 11 Y 17X 20 Null Null |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-06-30 : 17:36:39
|
No need for self-joining.DECLARE @Sample TABLE ( typ CHAR(1), tim INT )INSERT @SampleSELECT 'Y', 0 UNION ALLSELECT 'X', 3 UNION ALLSELECT 'Y', 7 UNION ALLSELECT 'X', 8 UNION ALLSELECT 'Y', 9 UNION ALLSELECT 'X', 11 UNION ALLSELECT 'Y', 17 UNION ALLSELECT 'X', 20SELECT MAX(CASE WHEN recID % 2 = 0 THEN typ ELSE NULL END) AS typ1, MAX(CASE WHEN recID % 2 = 0 THEN tim ELSE NULL END) AS tim1, MAX(CASE WHEN recID % 2 = 1 THEN typ ELSE NULL END) AS typ2, MAX(CASE WHEN recID % 2 = 1 THEN tim ELSE NULL END) AS tim2FROM ( SELECT typ, tim, ROW_NUMBER() OVER (ORDER BY tim) - 1 AS recID FROM @Sample WHERE tim > 0 ) AS dGROUP BY recID / 2ORDER BY recID / 2 N 56°04'39.26"E 12°55'05.63" |
 |
|
|
GrTech2009
Starting Member
6 Posts |
Posted - 2009-06-30 : 18:20:51
|
| What does UNION ALL mean? Also what role does % play in the following code snippet.SELECT MAX(CASE WHEN recID % 2 = 0 THEN typ ELSE NULL END) AS typ1, MAX(CASE WHEN recID % 2 = 0 THEN tim ELSE NULL END) AS tim1, MAX(CASE WHEN recID % 2 = 1 THEN typ ELSE NULL END) AS typ2, MAX(CASE WHEN recID % 2 = 1 THEN tim ELSE NULL END) AS tim2I always used it like this. SELECT * FROM Name WHERE FIRSTNAME LIKE '%Geo'Please explain thanks. |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-07-01 : 02:58:07
|
% means MODULO.The first part is only to setup a test environment.You should concentrate on the last statement, the SELECT query that starts with MAX(... N 56°04'39.26"E 12°55'05.63" |
 |
|
|
A.J.Gibson
Starting Member
9 Posts |
Posted - 2009-07-02 : 10:34:44
|
| Peso!Thanks for you're insight, you've definitely given me something to think about. The thing is: the actual table doesn't neccesarily alternate X/Y/X/Y because it has more than one object on it; so it's more like X1/X2/X3/Y2/X4/Y3/X2/Y1 with the object identified by another field; the example was a simplification. |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2009-07-02 : 11:20:42
|
| so in that case you always want a X value with next followed Y value? |
 |
|
|
A.J.Gibson
Starting Member
9 Posts |
Posted - 2009-07-02 : 11:38:37
|
| Let me do a more complicated example:Type Time NameX 03 Device1X 04 Thingy2X 07 Gizmo3Y 09 Thingy2X 12 Dohicky4Y 13 Device1X 15 Thingy2X 16 Device1Y 20 Device1Y 23 Gizmo3Y 27 Dohicky4Would result in:Start StartTime Name End EndTimeX 03 Device1 Y 13 Device1X 04 Thingy2 Y 09 Thingy2X 07 Gizmo3 Y 23 Gizmo3X 12 Dohicky4 Y 27 Dohicky4X 15 Thingy2 NULL 0X 16 Device1 Y 20 Device1Each X event is matched to the next Y event that has the same name, with an unfinished pair getting a null/0 instead |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2009-07-02 : 11:53:16
|
ok. try thisSELECT t.Type, t.Time, t.Name,t1.Type, COALESCE(t1.Time,0), t1.NameFROM YourTable tOUTER APPLY (SELECT TOP 1 Type, Time, Name FROM YourTable WHERE Time > t.Time AND Type ='Y' AND Name = t.Name ORDER BY Time ASC) t1WHERE t.Type='X' |
 |
|
|
A.J.Gibson
Starting Member
9 Posts |
Posted - 2009-07-02 : 12:19:01
|
| Is there any way I can not use Outer Apply? I'm not using SQL Server for this. |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-07-02 : 12:29:21
|
SELECT 'x',x.time,'y',y.timeFROM (SELECT Type, Time, ROW_NUMBER() OVER (ORDER BY time) as recid FROM Table1 WHERE Type = 'X') AS xFULL JOIN (SELECT Type, Time, ROW_NUMBER() OVER (ORDER BY time) as recid FROM Table1 WHERE Type = 'Y') AS y on y.recid = x.recidorder by coalesce(x.recid, y.recid) Microsoft SQL Server MVPN 56°04'39.26"E 12°55'05.63" |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2009-07-02 : 12:29:59
|
quote: Originally posted by A.J.Gibson Is there any way I can not use Outer Apply? I'm not using SQL Server for this.
then why posting in sql server forum? post it in relevant forum |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2009-07-02 : 12:31:43
|
quote: Originally posted by Peso SELECT 'x',x.time,'y',y.timeFROM (SELECT Type, Time, ROW_NUMBER() OVER (ORDER BY time) as recid FROM Table1 WHERE Type = 'X') AS xFULL JOIN (SELECT Type, Time, ROW_NUMBER() OVER (ORDER BY time) as recid FROM Table1 WHERE Type = 'Y') AS y on y.recid = x.recidorder by coalesce(x.recid, y.recid) Microsoft SQL Server MVPN 56°04'39.26"E 12°55'05.63"
Dont you need to link by Name values also? |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2009-07-02 : 12:35:30
|
Probably. I didn't read the last specification well.Add "PARTITION BY Name" before the "ORDER BY time".Add "AND y.Name = x.Name" to the JOIN clause.Add ", Name" to the both inner select lists.Add ", x.name" and ", y.name" to outer select list. Microsoft SQL Server MVPN 56°04'39.26"E 12°55'05.63" |
 |
|
|
|