Reputation: 183
I have a table:
Type | Value
1 | '1test1'
2 | '2test1'
2 | '2test2'
2 | '2test3'
I want to get a result containing a pair where each entry from each type is used at least once, but not more than required.
From the example table above, I want the following result:
1test1 - 2test1
1test1 - 2test2
1test1 - 2test3
If the table is:
Type | Value
1 | '1test1'
1 | '1test2'
1 | '1test3'
2 | '2test1'
2 | '2test2'
2 | '2test3'
I want the following result:
1test1 - 2test1
1test2 - 2test2
1test3 - 2test3
If the table is:
Type | Value
1 | '1test1'
1 | '1test2'
2 | '2test1'
2 | '2test2'
2 | '2test3'
I want the following result:
'1test1' - '2test1'
'1test2' - '2test2'
'1test1' - '2test3'
'1test1' - '2test1'
'1test2' - '2test2'
'1test1' - '2test3'
I want each type to be repeated equally as other values in the same type. There shouldn't be a value from type that is repeated more often than other values in the same type.
What is the most elegant way to do it with SQL or stored procedure, or with a series of SQL statements?
Upvotes: 0
Views: 279
Reputation: 3128
It is somewhat easy to do when you have you don't have the same amount of rows for each type, but once you do, it gets somewhat tricky.
So I came up with this:
CREATE PROCEDURE test()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE type1, type2 INT;
DECLARE value1, value2 VARCHAR(5);
DECLARE cur1 CURSOR FOR SELECT type,value FROM testtable WHERE Type = 1;
DECLARE cur1 CURSOR FOR SELECT type,value FROM testtable WHERE Type = 2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
if (SELECT COUNT(Value) FROM testtable WHERE Type = 1)
= (SELECT COUNT(Value) FROM testtable WHERE Type = 2)
then
OPEN cur1;
OPEN cur2;
CREATE TEMPORARY TABLE test1 (
Value1 varchar(12),
Value2 varchar(12)
)
read_loop: LOOP
FETCH cur1 INTO type1, value1;
FETCH cur2 INTO type2, value2;
IF done THEN
LEAVE read_loop;
END IF;
INSERT INTO test1 VALUES(value1, value2);
END LOOP;
CLOSE cur1;
CLOSE cur2;
SELECT * FROM test1;
DROP TABLE test1;
ELSE
SELECT t1.Value, t2.Value
FROM testtable t1
LEFT JOIN testtable t2 ON t2.Type = 2
WHERE t1.Type = 1
UNION SELECT t1.Value, t2.Value
FROM testtable t1
RIGHT JOIN testtable t2 ON t2.Type = 2
WHERE t1.Type = 1;
END IF;
END;
It's hideous, but it works for your three examples. Somewhat.
Upvotes: 1
Reputation: 19882
Is this what you want
SELECT
s.val AS One,
r.val AS Second
FROM stuff AS s
LEFT OUTER JOIN (SELECT * FROM stuff WHERE idx = 2) AS r ON r.idx <> s.idx
WHERE s.idx = 1
OUTPUT :
One | Second
--------------------
1val1 | 2val1
1val1 | 2val2
1val1 | 2val3
1val2 | 2val1
1val2 | 2val2
1val2 | 2val3
Upvotes: 1
Reputation: 10469
This is a somewhat contrived answer but I guess it fits the question:
create table stuff( idx tinyint unsigned, val varchar(50));
insert into stuff( idx, val ) values ( 1, '1val1'), (1, '1val2'), (2,'2val1'),
(2,'2val2'), (2, '2val3');
SELECT s0.val v0, s1.val v1 FROM stuff s0
JOIN stuff s1 ON s0.idx != s1.idx
where s0.idx = 1;
Here's a fiddle.
Upvotes: 1