Subquery has too many columns error while getting data for past X weeks?

我的未来我决定 提交于 2021-01-29 04:36:15

问题


I have below query which gives me data for previous week as shown below. It returns data with these columns: type, amount and total for previous week using week_number column which is used in inner subquery.

select type,
case
WHEN (type = 'PROC1' AND code = 'UIT') THEN 450
WHEN (type = 'PROC1' AND code = 'KJH') THEN 900
WHEN (type = 'PROC2' AND code = 'LOP') THEN 8840
WHEN (type = 'PROC2' AND code = 'AWE') THEN 1490
WHEN (type = 'PROC3' AND code = 'MNH') THEN 1600
WHEN (type = 'PROC3' AND code = 'LKP') THEN 1900
END as amount,
total
from xyz.orders pa
join
(select clientid as clientid, max(version) as version
from xyz.orders where consumerid IN (select distinct entity_id from abc.items
where week_number = extract(week from current_date) - 1
and item_type like '%Ionize - Data%' )
and createdfor ='BLOCK'
and holder='RELAY_FUTURES'
group by clientid) pb on
pa.clientid = pb.clientid and pa.version = pb.version;

Below is the output I get back as of now with my above query which is for previous week:

type    amount      total
---------------------------
PROC1    450         1768
PROC1    900         123
PROC1    450         456
PROC2    8840        99897
PROC2    1490        2223
PROC2    8840        9876
PROC3    1900        23456
PROC3    1600        12498
PROC3    1600        28756

In my above query I have inner subquery as shown below which returns data for previous week and then output of this is used in the outer query.

select distinct entity_id from abc.items
where week_number = extract(week from current_date) - 1
and item_type like '%Ionize - Data%'

Now I am trying to figure out a way by which I can get data for past 6 weeks (not including current week) and also grouped by each week so I think we need to modify above inner query so that it can give me data for past 6 weeks and then group by each week somehow at the outer query. Basically I want to get amount, total for each type for past 6 weeks as shown below. Somehow I need to add week_number column as well in my final output.

Expected Output

week_number     type    amount      total
--------------------------------------------
  46            PROC1    450         1768
  46            PROC1    900         123
  46            PROC1    450         456
  46            PROC2    8840        99897
  46            PROC2    1490        2223
  46            PROC2    8840        9876
  46            PROC3    1900        23456
  46            PROC3    1600        12498
  46            PROC3    1600        28756
  45            PROC1    450         1768
  45            PROC1    900         123
  45            PROC1    450         456
  45            PROC2    8840        99897
  45            PROC2    1490        2223
  45            PROC2    8840        9876
  45            PROC3    1900        23456
  45            PROC3    1600        12498
  45            PROC3    1600        28756
  44            PROC1    450         1768
  44            PROC1    900         123
  44            PROC1    450         456
  44            PROC2    8840        99897
  44            PROC2    1490        2223
  44            PROC2    8840        9876
  44            PROC3    1900        23456
  44            PROC3    1600        12498
  44            PROC3    1600        28756
  43            PROC1    450         1768
  43            PROC1    900         123
  43            PROC1    450         456
  43            PROC2    8840        99897
  43            PROC2    1490        2223
  43            PROC2    8840        9876
  43            PROC3    1900        23456
  43            PROC3    1600        12498
  43            PROC3    1600        28756
  42            PROC1    450         1768
  42            PROC1    900         123
  42            PROC1    450         456
  42            PROC2    8840        99897
  42            PROC2    1490        2223
  42            PROC2    8840        9876
  42            PROC3    1900        23456
  42            PROC3    1600        12498
  42            PROC3    1600        28756
  41            PROC1    450         1768
  41            PROC1    900         123
  41            PROC1    450         456
  41            PROC2    8840        99897
  41            PROC2    1490        2223
  41            PROC2    8840        9876
  41            PROC3    1900        23456
  41            PROC3    1600        12498
  41            PROC3    1600        28756

So I tried with below query by modifying inner subquery but it gives me error as invalid operation:subquery has too many columns. Any idea what is wrong I am doing here?

select type,
case
WHEN (type = 'PROC1' AND code = 'UIT') THEN 450
WHEN (type = 'PROC1' AND code = 'KJH') THEN 900
WHEN (type = 'PROC2' AND code = 'LOP') THEN 8840
WHEN (type = 'PROC2' AND code = 'AWE') THEN 1490
WHEN (type = 'PROC3' AND code = 'MNH') THEN 1600
WHEN (type = 'PROC3' AND code = 'LKP') THEN 1900
END as amount,
total
from xyz.orders pa
join
(select clientid as clientid, max(version) as version
from xyz.orders where consumerid IN (select week_number, entity_id from abc.items
where week_number >= extract(week from current_date) - 6 
  and week_number <= extract(week from current_date) - 1
  and item_type like '%Ionize - Data%'
order by week_number desc )
and createdfor ='BLOCK'
and holder='RELAY_FUTURES'
group by clientid) pb on
pa.clientid = pb.clientid and pa.version = pb.version;

I modified my inner query to be like this:

select week_number, entity_id from abc.items
where week_number >= extract(week from current_date) - 6 
  and week_number <= extract(week from current_date) - 1
  and item_type like '%Ionize - Data%'
order by week_number desc

It could be possible that I am doing it completely wrong to achieve the desired output so any help will be appreciated.


回答1:


Andy the issue is with the WHERE clause

where consumerid IN (select week_number, entity_id from abc.items
where week_number >= extract(week from current_date) - 6 
  and week_number <= extract(week from current_date) - 1
  and item_type like '%Ionize - Data%'
order by week_number desc )

As the clause is looking to see if "consumerid" is a member of the list resulting from the subquery. However this subquery is returning 2 columns and Redshift cannot compare 1 column to 2 columns. Just remove "week_number," from the select and this error will be resolved.

where consumerid IN (select entity_id from abc.items
where week_number >= extract(week from current_date) - 6 
  and week_number <= extract(week from current_date) - 1
  and item_type like '%Ionize - Data%'
order by week_number desc )



回答2:


The code below should suffice - not tested using Redshift interpreter however.

week_number: Replace the IN with join and select your week_number as below. It's not entirely clear which week_number you are looking for here. To the outsider, the max version is retrieved for a 5-week time boxed period, so if a record on xyz.orders has week 45 then the max version retrieved in the query below will be for Week 39 - Week 44.
So the query below should present the following:

Week 45, 
Type, 
Amount for latest in Week 39 - Week 44, 
Total. 

Negative week number - see commented code below.

With Maxfor5WeekPeriod as 
(
    select 
        MaxVersions.week_number,
        O.clientid as clientid, 
        max(O.version) as version
    from xyz.orders O
    join
    (
        select 
            entity_id,
            week_number
        from abc.items
        where 
        --Something like this should resolve your start of year issue. 
        date_part(w,dateadd(week,-6,current_date)) >= week_number 
        and date_part(w,dateadd(week,-1,current_date)) <= week_number
        and item_type like '%Ionize - Data%'
    ) MaxVersions on 
    entity_id = Consumerid 
    and O.createdfor ='BLOCK'
    and O.holder='RELAY_FUTURES'
    group by O.clientid,MaxVersions.week_number
)
select 
    M.week_number, 
    pa.type,
    case
    WHEN (pa.type = 'PROC1' AND contractdomicilecode = 'UIT') THEN 450
    WHEN (pa.type = 'PROC1' AND contractdomicilecode = 'KJH') THEN 900
    WHEN (pa.type = 'PROC2' AND contractdomicilecode = 'LOP') THEN 8840
    WHEN (pa.type = 'PROC2' AND contractdomicilecode = 'AWE') THEN 1490
    WHEN (pa.type = 'PROC3' AND contractdomicilecode = 'MNH') THEN 1600
    WHEN (pa.type = 'PROC3' AND contractdomicilecode = 'LKP') THEN 1900
    END as amount,
    pa.total
from 
xyz.orders pa
join Maxfor5WeekPeriod M 
on pa.clientid = M.clientid and 
pa.version = M.version

General point: Redshift docs include a reference to Common Table Expressions - they would make this code somewhat tidier. Answer does benefit significantly from earlier clarifications from the other contributors. However, please note I am not familiar with Redshift.




回答3:


To get all the distinct entity_id, week_number combination for the past 6 weeks.(Table 1)

SELECT DISTINCT entity_id, week_number
       FROM abc.items
       WHERE week_number >= Extract(week FROM CURRENT_DATE) - 6
         AND week_number <= Extract(week FROM CURRENT_DATE) - 1
         AND item_type LIKE '%Ionize - Data%'

To get the max version of orders corresponding to a unique combination of clientId and Consumer ID

SELECT clientid AS clientid, Max(version) AS version, consumerid
          FROM xyz.orders
          WHERE createdfor = 'BLOCK'
            AND holder = 'RELAY_FUTURES'
          GROUP BY consumerid, clientid

Join the above two tables to get clientId, version, and Week Number.

select xo.clientid    AS clientid,
             xo.version     AS version,
             ai.week_number as week_number from (SELECT DISTINCT entity_id, week_number
       FROM abc.items
       WHERE week_number >= Extract(week FROM CURRENT_DATE) - 6
         AND week_number <= Extract(week FROM CURRENT_DATE) - 1
         AND item_type LIKE '%Ionize - Data%')
         ai LEFT JOIN
         (SELECT clientid     AS clientid,
                 Max(version) AS version,
                 consumerid
          FROM xyz.orders
          WHERE createdfor = 'BLOCK'
            AND holder = 'RELAY_FUTURES'
          GROUP BY consumerid, clientid) xo
      ON ai.entity_id = xo.consumerid

Left join is used to discard all the consumer id not present in Table 1.

Use the above query as inner query.

SELECT pb.week_number,
       pa.type,
       CASE
           WHEN (type = 'PROC1'
               AND contractdomicilecode = 'UIT') THEN 450
           WHEN (type = 'PROC1'
               AND contractdomicilecode = 'KJH') THEN 900
           WHEN (type = 'PROC2'
               AND contractdomicilecode = 'LOP') THEN 8840
           WHEN (type = 'PROC2'
               AND contractdomicilecode = 'AWE') THEN 1490
           WHEN (type = 'PROC3'
               AND contractdomicilecode = 'MNH') THEN 1600
           WHEN (type = 'PROC3'
               AND contractdomicilecode = 'LKP') THEN 1900
           END AS amount,
       pa.total
FROM xyz.orders pa
         JOIN
     (select xo.clientid    AS clientid,
             xo.version     AS version,
             ai.week_number as week_number from (SELECT DISTINCT entity_id, week_number
       FROM abc.items
       WHERE week_number >= Extract(week FROM CURRENT_DATE) - 6
         AND week_number <= Extract(week FROM CURRENT_DATE) - 1
         AND item_type LIKE '%Ionize - Data%')
         ai LEFT JOIN
         (SELECT clientid     AS clientid,
                 Max(version) AS version,
                 consumerid
          FROM xyz.orders
          WHERE createdfor = 'BLOCK'
            AND holder = 'RELAY_FUTURES'
          GROUP BY consumerid, clientid) xo
      ON ai.entity_id = xo.consumerid) pb
     ON pa.clientid = pb.clientid
         AND pa.version = pb.version;


来源:https://stackoverflow.com/questions/64994981/subquery-has-too-many-columns-error-while-getting-data-for-past-x-weeks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!