This problem can also be solved in a very MySQL-specific way, using a variable. The variable will store a unique CSV list of values found in t1 and t2. The value of each column will first be tested against the list (if found, a null will be returned, otherwise the value), then added to the list (if absent from it).
This is my implementation of the above logic:
SELECT
id,
IF(FIND_IN_SET(t1, @list), NULL, t1) AS t1,
@list := CONCAT_WS(',', @list, IF(FIND_IN_SET(t1, @list), NULL, t1)),
IF(FIND_IN_SET(t2, @list), NULL, t2) AS t2,
@list := CONCAT_WS(',', @list, IF(FIND_IN_SET(t2, @list), NULL, t2))
FROM
(SELECT @list := '') AS x,
YourTable AS t
;
Updating the list is implemented in the form of additional computed columns without explicit aliases, namely these:
...
@list := CONCAT_WS(',', @list, IF(FIND_IN_SET(t1, @list), NULL, t1)),
...
@list := CONCAT_WS(',', @list, IF(FIND_IN_SET(t2, @list), NULL, t2))
...
Those columns are not needed in the output, they only serve as steps of the solution. In order to avoid returning them, use the query as a derived table, so that only the columns you want can be pulled from it:
SELECT
id,
t1,
t2
FROM
(
SELECT
id,
IF(FIND_IN_SET(t1, @list), NULL, t1) AS t1,
@list := CONCAT_WS(',', @list, IF(FIND_IN_SET(t1, @list), NULL, t1)),
IF(FIND_IN_SET(t2, @list), NULL, t2) AS t2,
@list := CONCAT_WS(',', @list, IF(FIND_IN_SET(t2, @list), NULL, t2))
FROM
(SELECT @list := '') AS x,
YourTable AS t
) AS derived
;
Note that the query does not specify an order in which the rows are read or returned. The solution will still work regardless of the row order but absence of an explicit ORDER BY ultimately means that the output might be different between different runs of the query. The issue is actually twofold. Because the rows are read without an explicit order, the query might produce different rows for the output, and the other problem is that they may also be returned in different order with each run of the query.
To resolve this and make the output completely repeatable, you probably need to supply an ORDER BY both at the nested level and at the outer level, something like this:
SELECT
id,
t1,
t2
FROM
(
SELECT
id,
IF(FIND_IN_SET(t1, @list), NULL, t1) AS t1,
@list := CONCAT_WS(',', @list, IF(FIND_IN_SET(t1, @list), NULL, t1)),
IF(FIND_IN_SET(t2, @list), NULL, t2) AS t2,
@list := CONCAT_WS(',', @list, IF(FIND_IN_SET(t2, @list), NULL, t2))
FROM
(SELECT @list := '') AS x,
YourTable AS t
ORDER BY
id ASC
) AS derived
ORDER BY
id ASC
;
An online demo of this solution can be found at Rextester or dbfiddle.uk. (The test setup was borrowed from ypercubeᵀᴹ's demo.)