问题
Using this sample dataset:
CREATE TABLE test. test2 (id VARCHAR(7), AA INT, BBB INT, CCC VARCHAR (12));
INSERT INTO test.test2 (id, AA, BBB,CCC) VALUES ( 'A123', 45, 123, '2011-03' );
INSERT INTO test.test2 (id, AA, BBB,CCC) VALUES ( 'A120', 52, 120, '2011-03' );
INSERT INTO test.test2 (id, AA, BBB,CCC) VALUES ( 'A133', 63, 133, '2011-03' );
INSERT INTO test.test2 (id, AA, BBB,CCC) VALUES ( 'D123', 34, 123, '2011-04' );
INSERT INTO test.test2 (id, AA, BBB,CCC) VALUES ( 'D120' ,32, 120, '2011-04' );
INSERT INTO test.test2 (id, AA, BBB,CCC) VALUES ( 'D140', 12, 140, '2011-04' );
Im look for table with 3 column.
Col A "Id" order as Desc from orginal.
Col B "Id2" as previous or next row Id in col A where CCC are the same.
Id, Id2 CCC
A120 A123 '2011-03'
A123 A133 '2011-03'
A133 '2011-03'
D120 D123 '2011-04'
D123 D140 '2011-04'
D140 '2011-04'
or
Id, Id2 CCC
A120 '2011-03'
A123 A120 '2011-03'
A133 A123 '2011-03'
D120 '2011-04'
D123 D120 '2011-04'
D140 D123 '2011-04'
OR
Id, Id2 CCC
A123 A120 '2011-03'
A133 A123 '2011-03'
D123 D120 '2011-04'
D140 D123 '2011-04'
Could I add an autocrement col to joined table, then use 1, 2, 3 rows up or down? The id2 would then be based on this autocrement row?
回答1:
Operating on Marc's basis:
SELECT test.id, child.id, test.CCC
FROM test
LEFT JOIN test AS child
ON (test.CCC = child.CCC)
AND (test.id < child.id)
WHERE NOT EXISTS
( SELECT 1
FROM test AS middle
WHERE (test.CCC = middle.CCC)
AND (test.id < middle.id)
AND (middle.id < child.id)
)
OR child.id IS NULL
ORDER BY test.id
This might be helpful with more complex queries:
CREATE VIEW testWithRowId AS
( SELECT test.id
, COUNT(test.id) AS rownum
, test.CCC
FROM test
JOIN test AS child
ON (test.CCC = child.CCC)
AND (test.id >= child.id)
GROUP BY test.CCC
, test.id
)
and then use it:
SELECT t1.id
, t2.id AS idShifted
, t1.CCC
FROM testWithRowId t1
LEFT JOIN testWithRowId t2
ON (t2.CCC = t1.CCC)
AND (t2.rownum = t1.rownum + 1) ---- replace this 1 with 2 or 3, etc
ORDER BY t1.CCC ---- for a shift 2 or shift 3, etc
, t1.rownum
回答2:
SELECT test.id, child.id, test.CCC
FROM test
LEFT JOIN test AS child ON ((test.CCC = child.CCC) and (test.id < child.id))
gets close:
+------+------+---------+
| id | id | CCC |
+------+------+---------+
| A120 | A123 | 2011-03 |
| A120 | A133 | 2011-03 |
| A123 | A133 | 2011-03 |
| A133 | NULL | 2011-03 |
| D120 | D123 | 2011-04 |
| D120 | D140 | 2011-04 |
| D123 | D140 | 2011-04 |
| D140 | NULL | 2011-04 |
+------+------+---------+
回答3:
Select T.Id, NextTest.NextId As Id2, T.CCC
From Test2 As T
Left Join (
Select T1.Id, Min( T2.Id ) As NextId
From Test2 As T1
Left Join Test2 As T2
On T2.CCC = T1.CCC
And T2.Id > T1.Id
Group By T1.Id
) As NextTest
On NextTest.Id = T.Id
Order By T.Id
This should return exactly what you have in your first set of desired output.
来源:https://stackoverflow.com/questions/5750355/mysql-sql-self-join