在MySQL中配对两种类型的值

时间:2013-03-09 12:39:25

标签: mysql sql

我有一张桌子:

Type | Value
1    | '1test1'
2    | '2test1'
2    | '2test2'
2    | '2test3'

我想得到一个包含一对的结果,其中每种类型的每个条目至少使用一次,但不超过要求。

从上面的示例表中,我想要以下结果:

1test1 - 2test1
1test1 - 2test2
1test1 - 2test3

如果表格是:

Type | Value
1    | '1test1'
1    | '1test2'
1    | '1test3'
2    | '2test1'
2    | '2test2'
2    | '2test3'

我想要以下结果:

1test1 - 2test1
1test2 - 2test2
1test3 - 2test3

如果表格是:

Type | Value
1    | '1test1'
1    | '1test2'
2    | '2test1'
2    | '2test2'
2    | '2test3'

我想要以下结果:

'1test1' - '2test1'
'1test2' - '2test2'
'1test1' - '2test3'
'1test1' - '2test1'
'1test2' - '2test2'
'1test1' - '2test3'

我希望每种类型与同一类型的其他值一样重复。类型中的值不应该比同一类型中的其他值更频繁地重复。

使用SQL或存储过程或一系列SQL语句执行此操作的最优雅方法是什么?

3 个答案:

答案 0 :(得分:1)

这是一个有点人为的答案,但我想它符合这个问题:

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;

这是fiddle

答案 1 :(得分:1)

这就是你想要的吗

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

SQL Fiddle Demo

输出:

One     |   Second
--------------------
1val1   |   2val1
1val1   |   2val2
1val1   |   2val3
1val2   |   2val1
1val2   |   2val2
1val2   |   2val3

答案 2 :(得分:1)

如果你没有为每种类型提供相同数量的行,这有点容易,但是一旦你做了,就会有点棘手。

所以我想出了这个:

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;

这很可怕,但它适用于你的三个例子。一些。