简体   繁体   中英

Scalar subquery produced more than one element, using UNNEST

I have the following sentence, as I have read, the UNNEST should be used, but I don't know how

select
(
  select 
    case 
      when lin = 4 then 1
      when lin != 4 then null
    end as FLAG,
  from table_1
  WHERE
    table_1.date = table_2.date
  AND
    table_1.acc = table_2.acc
) as FLAG
FROM
  table_2

I have a lot of subqueries and that's why I can't use LEFT JOIN. Currently my table_2 has 13 million records, and table_1 has 400 million records, what I want is to be able to show a FLAG for each account, knowing that the data universes are different.

I can't use LEFT JOIN ...
Scalar subquery produced more than one element ...

simply use below version of your query - which logically is equivalent to your original query but eliminating the issue you have

select *, 
(
  select 1 as FLAG
  from table_1
  WHERE
    table_1.date = table_2.date
  AND
    table_1.acc = table_2.acc
  AND lin = 4
  LIMIT 1
) as FLAG
FROM
  table_2

This indicates that you expect to see one and only one value from the subquery but when you join to table_1 you are getting duplicates on the date and acc fields. If you aggregate the value or remove the duplicates from table_1 that should solve your issue, although at that point why not just use a more efficient JOIN ?

-- This will solve your immediate problem, use any aggregation
-- technique, I picked MAX because why not. I do not know your use case.
select
(
  select 
    MAX(case 
      when lin = 4 then 1
      when lin != 4 then null
    end) as FLAG
  from table_1
  WHERE
    table_1.date = table_2.date
  AND
    table_1.acc = table_2.acc
) as FLAG
FROM
  table_2

A better way to do this would be

select
  case 
    when t1.lin = 4 then 1
    when t1.lin != 4 then null
  end as FLAG
FROM
  table_2 t2
LEFT JOIN
  table_1 t1 ON (
    t1.date = t2.date
    AND t1.acc = t2.acc
  )

As you said, left joins do not work for you. If you want multiple results to be nested in the same subquery then just wrap your subquery in an ARRAY() function to allow for repeated values.

select
ARRAY(
  select 
    case 
      when lin = 4 then 1
      when lin != 4 then null
    end as FLAG
  from table_1
  WHERE
    table_1.date = table_2.date
  AND
    table_1.acc = table_2.acc
  
  -- Now you must filter out results that will return
  -- NULL because NULL is not allowed in an ARRAY
  AND
    table_1.lin = 4

) as FLAG
FROM
  table_2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM