0

私はテーブルを持っています:

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

各タイプの各エントリが少なくとも 1 回は使用されるが、必要以上に使用されないペアを含む結果を取得したいと考えています。

上記の表の例から、次の結果が必要です。

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 ステートメントを使用してそれを行う最も洗練された方法は何ですか?

4

3 に答える 3

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;

それは恐ろしいですが、あなたの3つの例で機能します。幾分。

于 2013-03-09T14:45:23.637 に答える
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;

これがフィドルです。

于 2013-03-09T13:22:01.767 に答える
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フィドルデモ

出力:

One     |   Second
--------------------
1val1   |   2val1
1val1   |   2val2
1val1   |   2val3
1val2   |   2val1
1val2   |   2val2
1val2   |   2val3
于 2013-03-09T13:25:41.530 に答える