问题
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