web-dev-qa-db-ja.com

UNION ALLまたは一時テーブルを使用せずに、格納された各行を2回表示するにはどうすればよいですか?

empという名前の関連テーブルには、次のデータが含まれています。

CREATE TEMPORARY TABLE emp AS
SELECT * FROM ( VALUES (1,'A'), (2,'B'), (3,'C') );

 ID  Name
 --  ----
 1    A
 2    B
 3    C

また、データ操作操作の出力または結果セットは、次のようになります。

 ID  Name 
 --  ----
 1    A
 1    A 
 2    B
 2    B
 3    C
 3    C

必要条件

次の条件に従って出力を取得する必要があります。

  • 採用されたSELECTステートメントに関連してUNION ALL演算子を使用しない
  • 一時テーブルを使用しない
  • 既存のテーブルに対するUPDATE操作の使用はありません

:このシナリオはインタビュアーによって持ち込まれました。

7
Anup
SELECT ta.id, ta.name
FROM emp ta 
CROSS JOIN ( VALUES (1), (2) ) tb (id) ;
16
paparazzo

一つの方法は

SELECT COALESCE(a.id, b.id) AS id,
       COALESCE(a.name, b.name) AS name
FROM emp a 
     FULL OUTER JOIN emp b ON 1=0
ORDER BY id;
10
Martin Smith

さらに3つの方法。

パパラッチの回答と同様に、NATURAL結合がCROSS結合になることを利用して、共通の列がない場合:

SELECT e.id, e.name
FROM emp AS e 
  NATURAL JOIN
    (VALUES (1), (2)) AS c (i) ;

もう1つはUNION DISTINCTと追加の列を使用して重複の削除を回避します。

SELECT id, name
FROM 
    ( SELECT id, name, 1 AS d
      FROM emp
      UNION 
      SELECT id, name, 2
      FROM emp
    ) AS t ; 

不正使用GROUPING SETS。返される行数を乗算するためにGROUP BYを使用するため、このメソッドには予想外の皮肉な点があります。

SELECT id, name
FROM emp 
GROUP BY GROUPING SETS ((id, name), (id, name)) ;
9
ypercubeᵀᴹ

onlyという別のソリューションは、指定されたサンプルデータで機能します。

select e1.*
from emp e1
  join emp e2 on e1.id <> i2.id;

要件またはサンプルデータが少しだけ異なる場合、これは機能しません。ただし、行数を2倍にする必要性は、IDごとに異なる2つのIDを正確に含むサンプルデータに適合します。 4つの異なるIDがある場合、これは動作しません。

本当に必要なのは、2行のテーブルへのクロス結合だけです。そこにあるものを使うことができます。

select e1.*
from emp e1
  cross join (select 1 from emp limit 2) tmp;

http://sqlfiddle.com/#!9/15057/ -暗黙の一時テーブルを使用するため、禁止される場合もあります。

select e1.*
from emp e1
  join emp e2 on e2.id IN (1, 2)
order by e1.id;

http://sqlfiddle.com/#!9/15057/6 -IN()条件を使用して2つの行を選択し、それらを使用して重複を生成します。

1
jkavalik

PostgreSQLを使用している場合は、_ORDER BY_句に SET RETURN FUNCTION を挿入します。

_CREATE TABLE foo AS
SELECT *
FROM ( VALUES (1,'A'),(2,'B'),(3,'C') ) AS x(id,name);
_

その後

_SELECT id,name
FROM foo
ORDER BY 1, generate_series(1,2);

 id | name 
----+------
  1 | A
  1 | A
  2 | B
  2 | B
  3 | C
  3 | C
_

_generate_series_である必要はありません。unnest('{1,2}'::int[])を使用することもできます。また、選択リストを使用することもできます(出力にシリーズが表示される場合を除きます)。

0
Evan Carroll