Error: subquery should return only one column

I get a subquery must return only one column error when I try to execute the following query:

 SELECT mat.mat as mat1, sum(stx.total ) as sumtotal1, ( SELECT mat.mat as mat, sum(stx.total) as sumtotal FROM stx LEFT JOIN mat ON stx.matid = mat.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 ) AS MyField FROM stx LEFT JOIN mat ON stx.matid = mat.matid LEFT JOIN sale ON stx.saleid = sale.id WHERE stx.date BETWEEN '2013-05-01' AND '2013-08-31' AND sale.userid LIKE 'B%' GROUP BY mat.mat 

What causes this error?

+6
source share
2 answers

Place a subquery that returns multiple columns in the FROM list and select from it.

A correlated subquery would be a bad idea to start with. However, your query is not even correlated, but unrelated (without reference to an external query) and seems to return multiple rows. This leads to a (possibly very expensive and meaningless) cross-coupling that creates Cartesian products, perhaps not your (secret) intention.

It looks like you really want:

 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); 

Both LEFT JOIN also meaningless. The one on sale forced to INNER JOIN the WHERE clause. What on the mat seems pointless since you are GROUP BY mat.mat - unless you are interested in mat IS NULL ? (I doubt).

This could probably be simplified:

 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; 

Perhaps the WHERE may be simplified, depending on your secret data types and indexes. Boat information about this case in this related answer to dba.SE.

+7
source

Instead of a subquery select statement

 SELECT mat.mat as mat, sum(stx.total) as sumtotal 

Try this statement.

 SELECT sum(stx.total) as sumtotal 
+1
source

Source: https://habr.com/ru/post/956912/


All Articles