sql >> データベース >  >> RDS >> PostgreSQL

エラー:サブクエリは1つの列のみを返す必要があります

    FROMに複数の列を返すサブクエリを配置します リストして、そこから選択します。

    相関サブクエリは、そもそも悪い考えです。ただし、クエリは相関していませんが、無関係 (外部クエリへのリンクなし)、複数の行を返すようです。これにより、(おそらく非常に高価で無意味な)クロス結合がデカルト積を生成しますが、おそらくあなたの(秘密の)意図ではありません。

    本当に欲しいようです:

    SELECT m1.mat AS mat1, m1.sumtotal AS sumtotal1
          ,m2.mat AS mat2, m2.sumtotal AS sumtotal2
    FROM (
       SELECT mat.mat, sum(stx.total) AS sumtotal
       FROM   stx 
       LEFT   JOIN mat ON mat.matid = stx.matid
       LEFT   JOIN sale ON stx.saleid = sale.id
       WHERE  stx.date BETWEEN '2013-05-01' AND '2013-08-31'
       AND    sale.userid LIKE 'A%'
       GROUP  BY mat.mat
       ) m1
    JOIN  (
       SELECT mat.mat, sum(stx.total) AS sumtotal
       FROM   stx 
       LEFT   JOIN mat ON mat.matid = stx.matid
       LEFT   JOIN sale ON sale.id = stx.saleid
       WHERE  stx.date BETWEEN '2013-05-01' AND '2013-08-31' 
       AND    sale.userid LIKE 'b%'
       GROUP  BY mat.mat
       ) m2 USING (mat);
    

    両方のLEFT JOIN また、無意味です。 saleのもの INNER JOINに強制されます WHERE条件によって。 GROUP BY mat.matなので、マット上のものは無意味に見えます -mat IS NULLに関心がある場合を除く ? (私はそれを疑う。)

    ケースはおそらくさらに単純化して次のようになります。

    SELECT m.mat
          ,sum(CASE WHEN s.userid LIKE 'A%' THEN x.total END) AS total_a
          ,sum(CASE WHEN s.userid LIKE 'B%' THEN x.total END) AS total_b
    FROM   sale s 
    JOIN   stx  x ON x.saleid = s.id
    JOIN   mat  m ON m.matid = x.matid
    WHERE (s.userid LIKE 'A%' OR s.userid LIKE 'B%')
    AND    x.date BETWEEN '2013-05-01' AND '2013-08-31'
    GROUP  BY 1;
    

    WHERE シークレットデータ型とインデックスによっては、条件をさらに単純化できる可能性があります。 dba.SEに関するこの関連する回答



    1. SQLステートメントがSELECTという単語で始まるかどうかを判別します

    2. Oracleで大量のデータを使用して同じテーブルでフィールド比較を行う最速の方法

    3. OracleSQLDeveloperでのExplainPlanの実行の結果を理解する

    4. SQLの切り捨て