SSRS DataSet different fields dependant on parameter - tsql

I am supplying a dataset to my SSRS report using a stored proc. Within my stored proc is a parameter called #ReportType. I use this as I have two reports which use the same subset of data however they return different columns based on the #ReportType and in one the report types I aggregate the data.
So for example the end of my stored proc is as follows:
---Income
IF #Rpt_Type = 'Income'
BEGIN
SELECT
EXPENSE_TYPE
, ACCOUNT_NAME
, CURRENCY
, SETTLEMENT_DATE
, ISSUE
, ISSUE_DESCRIPTION
, SETTLEMENT_AMOUNT
, TRANSACTION_STATUS
, TRANSACTION_CATEGORY
, TRANSACTION_SUBCATEGORY
, TRANSACTION_DESCRIPTION
FROM #RESULT_SET
WHERE TRANSACTION_CATEGORY IN ('IN','IF') OR (TRANSACTION_CATEGORY IN ('CD','CW') AND TRANSACTION_SUBCATEGORY IN ('INT','SLI','RDS','INS','INC'))
ORDER BY expense_type,settlement_date,issue_description
END
---Expenses
IF #Rpt_Type = 'Expenses'
BEGIN
BEGIN
SELECT
ACCOUNT_NAME AS [Portfolio_Number]
, TRANSACTION_SUBCATEGORY AS [Cash_flow_type]
, TRANSACTION_DESCRIPTION AS [Cash_Flow_Description]
, COUNT(ACCOUNT_NAME) AS [Number Of Transactions]
, #ReportEndDate AS [EndDate]
FROM #RESULT_SET
WHERE TRANSACTION_SUBCATEGORY IN ('CCD','CCW','FSB','FSS','FFB','FFS','FSO','FSC','FFO','FFC')
AND INQ_BASIS_NUM = '1'
GROUP BY ACCOUNT_NAME,TRANSACTION_SUBCATEGORY,TRANSACTION_DESCRIPTION,TRANSACTION_CATEGORY
ORDER BY ACCOUNT_NAME,TRANSACTION_SUBCATEGORY,TRANSACTION_DESCRIPTION,TRANSACTION_CATEGORY
END
My question is how can I get SSRS to return the different columns for each report type? Is there a way in how I create the dataset that I can give the parameter before the columns are returned into SSRS for me to use? Will I have to create two datasets in SSRS to cater for the different columns required?

This will work so long as you return the same column names for each #Rpt_Type. For #Rpt_Type 'Income', return NULL values for the #Rpt_Type 'Expenses' data, and vice versa. Otherwise, the report will expect columns that it isn't getting from the dataset and the dataset will fail:
---Income
IF #Rpt_Type = 'Income'
BEGIN
SELECT
EXPENSE_TYPE
, ACCOUNT_NAME
, CURRENCY
, SETTLEMENT_DATE
, ISSUE
, ISSUE_DESCRIPTION
, SETTLEMENT_AMOUNT
, TRANSACTION_STATUS
, TRANSACTION_CATEGORY
, TRANSACTION_SUBCATEGORY
, TRANSACTION_DESCRIPTION
, NULL Portfolio_Number
, NULL Cash_flow_type
, NULL Cash_Flow_Description
, NULL [Number Of Transactions]
, NULL EndDate
FROM #RESULT_SET
WHERE TRANSACTION_CATEGORY IN ('IN','IF') OR (TRANSACTION_CATEGORY IN ('CD','CW') AND TRANSACTION_SUBCATEGORY IN ('INT','SLI','RDS','INS','INC'))
ORDER BY expense_type,settlement_date,issue_description
END
---Expenses
IF #Rpt_Type = 'Expenses'
BEGIN
BEGIN
SELECT NULL EXPENSE_TYPE
, NULL ACCOUNT_NAME
, NULL CURRENCY
, NULL SETTLEMENT_DATE
, NULL ISSUE
, NULL ISSUE_DESCRIPTION
, NULL SETTLEMENT_AMOUNT
, NULL TRANSACTION_STATUS
, NULL TRANSACTION_CATEGORY
, NULL TRANSACTION_SUBCATEGORY
, NULL TRANSACTION_DESCRIPTION
, ACCOUNT_NAME AS [Portfolio_Number]
, TRANSACTION_SUBCATEGORY AS [Cash_flow_type]
, TRANSACTION_DESCRIPTION AS [Cash_Flow_Description]
, COUNT(ACCOUNT_NAME) AS [Number Of Transactions]
, #ReportEndDate AS [EndDate]
FROM #RESULT_SET
WHERE TRANSACTION_SUBCATEGORY IN ('CCD','CCW','FSB','FSS','FFB','FFS','FSO','FSC','FFO','FFC')
AND INQ_BASIS_NUM = '1'
GROUP BY ACCOUNT_NAME,TRANSACTION_SUBCATEGORY,TRANSACTION_DESCRIPTION,TRANSACTION_CATEGORY
ORDER BY ACCOUNT_NAME,TRANSACTION_SUBCATEGORY,TRANSACTION_DESCRIPTION,TRANSACTION_CATEGORY
END

Related

Postgres - Return the results from multiple rows

I have the below tables:
CREATE SCHEMA pulse;
CREATE TABLE pulse.event(
id integer,
url text,
name text,
event_start date,
event_end date,
sub_type text,
preference jsonb
);
CREATE TABLE pulse.event_meta(
event_id integer,
data json
);
CREATE TABLE pulse.slot_archive(
id integer,
event_id integer,
location_id integer,
date text,
start_time text,
end_time text,
current_registration integer,
preference json
);
CREATE TABLE pulse.event_booking_archive(
id integer,
event_id integer,
slot_id integer,
status text,
data json
);
The below query retrieves the event when the status is canceled (From the event table, preference column) along with additional data from other tables.
Query:
Select
COALESCE((evnt.preference::json #>> '{eventStatus,status}' is not null)::boolean, false) as "eventCancelled",
COALESCE(attendancecount,0) as "attendanceCount",
COALESCE((meta.data ->> 'walkins')::int, 0) as walkins,
COALESCE((meta.data ->> 'attendanceSubmitted')::boolean, false) as "attendanceSubmitted",
meta.data -> 'heroImage' as "heroImage",
meta.data -> 'tileContent' -> 'registrationPage' ->> 'title' as title,
evnt.id as "eventId",
evnt.url as "eventUrl",
evnt.name as name,
evnt.event_start AT TIME ZONE 'America/New_York' as "startTime",
evnt.event_end AT TIME ZONE 'America/New_York' as "endTime",
evnt.sub_type as "subType",
agg_slot.slotDates as slots,
agg_slot.registrationcount as "registrationCount" from pulse.event as evnt
inner join pulse.event_meta meta on evnt.id = meta.event_id
left join (select event_id, COALESCE(sum((data ->> 'attendanceCount')::int),0) as attendancecount from pulse.event_booking_archive where status = 'SUCCESS' group by event_id) as eb
on evnt.id = eb.event_id,
(select event_id, location_id, array_agg(CONCAT_WS(' ', slot.date,slot.start_time,slot.end_time)) as slotDates, sum(current_registration) as registrationCount from pulse.slot_archive as slot
group by slot.event_id, slot.location_id) as agg_slot
where evnt.id = agg_slot.event_id
and evnt.id in (select id from pulse.event where event_end + interval '48h' < now())
and agg_slot.location_id = '3305';
But, I need help in finding out the event whose event location is canceled. i.e All the slots for that particular event location_id in the slot_archive table have "statusMeta": "CS". I'm stuck here. Can someone please assist?
https://www.db-fiddle.com/f/iqxvqrjDrqb8B3tG1xzpHN/14
I rewrote your request to makes it more clear.
So we have :
With booking_archive_success as
(select event_id, COALESCE(sum((data ->> 'attendanceCount')::int),0) as attendancecount
from pulse.event_booking_archive where status = 'SUCCESS'
group by event_id)
, agg_slot as (
select slot.event_id, slot.location_id
, array_agg(CONCAT_WS(' ', slot.date,slot.start_time,slot.end_time)) as slotDates
, sum(slot.current_registration) as registrationCount
, array_agg(slot.preference->'slotStatus'->>'statusMeta') as statuses
from pulse.slot_archive as slot
group by slot.event_id, slot.location_id)
select COALESCE((evnt.preference::json #>> '{eventStatus,status}' is not null)::boolean, false) as "eventCancelled"
, COALESCE(attendancecount,0) as "attendanceCount"
, COALESCE((meta.data ->> 'walkins')::int, 0) as walkins
, COALESCE((meta.data ->> 'attendanceSubmitted')::boolean, false) as "attendanceSubmitted"
, meta.data -> 'heroImage' as "heroImage"
, meta.data -> 'tileContent' -> 'registrationPage' ->> 'title' as title
, evnt.id as "eventId"
, evnt.url as "eventUrl"
, evnt.name as name
, evnt.event_start AT TIME ZONE 'America/New_York' as "startTime"
,evnt.event_end AT TIME ZONE 'America/New_York' as "endTime"
--, evnt.type as type
, evnt.sub_type as "subType"
, agg_slot.slotDates as slots
, agg_slot.registrationcount as "registrationCount"
, agg_slot.statuses
from pulse.event as evnt
inner join pulse.event_meta meta on evnt.id = meta.event_id
left join booking_archive_success as eb on evnt.id = eb.event_id
inner join agg_slot on evnt.id = agg_slot.event_id
where evnt.id in
(select id from pulse.event where event_end + interval '48h' < now())
and not exists (Select 1 from (Select unnest(agg_slot.statuses) as statusMeta from agg_slot a Where a.event_id = evnt.id) t
where statusMeta not like 'CS' or statusMeta is null
)
and agg_slot.location_id = '3305';
Several good habits to take :
Prefer the using of CTE when it is possible. The code is more readable, and easier to conceive
Avoid Cartesian Product in the from with the join condition in the where, so I fixed it by using an inner join clause
To solve (I hope) your problem, I used the unnest function in a "not exists" condition in the where. The goal is to forbid every eventid where one of the statusMeta is not CS

Report an amount field by a value in another field

I have a large table that has a structure something like the following:
Create Table public.example
(
id character varying(7) ,
type character varying(1) ,
amount decimal ,
date1 date ,
plan character varying(2) ,
date2 date );
Insert into public.example
( Id,Type,Amount,Date1,Plan,Date2)
values
( '1343657' , 'e',235.26 ,'2021-01-03', 'HS', '2021-07-03'),
( '1343657' , 's',6234.25,'2021-01-15', 'RT', '2021-05-09'),
( '1343657' , 's',235.26 ,'2021-01-05', 'HS', '2021-05-03'),
( '1343657' , '3',235.26 ,'2021-01-05', 'HS', '2021-05-17'),
( '1343657' , 's',235.26 ,'2021-01-05', 'HS', '2021-03-19'),
( '5364324' , 'e',1245.90,'2021-01-17', 'MM', '2021-04-23'),
( '5364324' , '1',5285.88,'2021-01-14', 'MM', '2021-02-28'),
( '5364324' , 'e',1245.10,'2021-01-08', 'VI', '2021-06-30'),
( '5364324' , 'e',7452.05,'2021-01-10', 'DT', '2021-03-07') ;
I need to list the "amount" field across the report in different buckets based on the value of the “Plan” field. I also need to summarize the amount by Id and Type. My method doesn’t work because it adds another required Group BY and I don’t get a summarized amount by Id and Type.
Select id,type,
case When a.plan ='HS' then sum(amount) else 0 end as "HS",
case When a.plan ='RT' then sum(amount) else 0 end as "RT",
case When a.plan ='MM' then sum(amount) else 0 end as "MM",
case When a.plan ='VI' then sum(amount) else 0 end as "VI",
case When a.plan ='DT' then sum(amount) else 0 end as "DT"
from public.example a
where date2>='2021-01-01' and date2<='2021-12-31'
group by 1,2,a.plan
The perfect solution would allow me to add date1 to the Select output as well.
Select OUTPUT
Thx

The error message is [Amazon](500310) Invalid operation: This type of correlated subquery pattern is not supported due to internal error

This is the query
CREATE TABLE dw_prestage.check_fact_update
AS
SELECT transaction_id,
transaction_line_id,
subsidiary_id
FROM ( SELECT transaction_id,
transaction_line_id,
subsidiary_id
FROM( SELECT
document_number ,
transaction_number ,
transaction_id ,
transaction_line_id ,
transaction_order ,
custom_form_id ,
document_status ,
transaction_type ,
currency_id ,
trandate ,
exchange_rate ,
account_id ,
amount ,
amount_foreign ,
gross_amount ,
net_amount ,
net_amount_foreign ,
quantity ,
item_id ,
item_unit_price ,
tax_item_id ,
tax_amount ,
location_id ,
class_id ,
subsidiary_id ,
accounting_period_id ,
check_id ,
check_type ,
created_by_id ,
create_date ,
date_last_modified ,
trx_type ,
memo
FROM dw_prestage.check_fact a2
WHERE NOT EXISTS ( SELECT 1 FROM dw_prestage.check_fact_insert b2
WHERE b2.transaction_id = a2.transaction_id
AND b2.transaction_line_id = a2.transaction_line_id
AND a2.subsidiary_id = b2.subsidiary_id
)
MINUS
SELECT
document_number ,
transaction_number ,
transaction_id ,
transaction_line_id ,
transaction_order ,
custom_form_id ,
document_status ,
transaction_type ,
currency_id ,
trandate ,
exchange_rate ,
account_id ,
amount ,
amount_foreign ,
gross_amount ,
net_amount ,
net_amount_foreign ,
quantity ,
item_id ,
item_unit_price ,
tax_item_id ,
tax_amount ,
location_id ,
class_id ,
subsidiary_id ,
accounting_period_id ,
check_id ,
check_type ,
created_by_id ,
create_date ,
date_last_modified ,
trx_type ,
memo
FROM dw_stage.check_fact a1
WHERE EXISTS ( SELECT 1 FROM dw_prestage.check_fact b1
WHERE b1.transaction_id = a1.transaction_id
AND b1.transaction_line_id = a1.transaction_line_id
AND a1.subsidiary_id = b1.subsidiary_id
)
)
) a
WHERE NOT EXISTS (SELECT 1
FROM dw_prestage.check_fact_insert aa
WHERE aa.transaction_id = a.transaction_id
AND aa.transaction_line_id = a.transaction_line_id);
plz suggest any alternative way to replace this query.
The error is because the queries in your NOT EXISTS clauses reference a table outside of the of the clause. Convert the NOT EXISTS clause into a LEFT JOIN with a predicate to exclude any matches. This pattern is often called an "anti-join".
Current:
FROM (…) a
WHERE NOT EXISTS (SELECT 1
FROM dw_prestage.check_fact_insert aa
WHERE aa.transaction_id = a.transaction_id
AND aa.transaction_line_id = a.transaction_line_id)
Rewrite:
FROM (…) a
LEFT JOIN dw_prestage.check_fact_insert aa
ON a.transaction_id = aa.transaction_id
AND a.transaction_line_id = aa.transaction_line_id
WHERE aa.transaction_id IS NULL

How to combine multiple tables and allow a "like" text search option for filtering, including if the criteria was left blank

I have 3 different tables where I want to be able to combine them and then filter them based off of 4 different inputs OR LESS on a search. I also would like to have it work when some filters are none.. Here is the breakdown what I mean:
So above there are three tables with column names and some data. NOTE: Table 1 has a comma in the location and I will want to separate those as two separate column for searching purposes which I figured out how to do.
Now What the final table I want is:
Table 1
------------------------------------------------
date city state title summary
jan 1 stl MO Book
jan 1 ATL MO Comp
Jan 1 Maine Phone box device
March2 MO Howey weird name
JUL2 cheese
Now My goal is trying to do a text search such as what follows: The 4 criteria of filtering will be State, Title, Date, OR a keyword
I think the solution has involves joining the tables, splitting the comma, using "where true" and having some type of IF statement.
select
date1,
split_part(location1, ',', 1) as city,
split_part(location1, ',', 2) as state,
title1
from
table1
Now I use join or union or something to add other tables?
Note: Null means user didn't have input at all
Example 1: If Date is Jan 1, state is null, title is null, Keyword is null (it should show everything with jan1st)
Example 2: If Date is Jan 1 AND City is stl (show first row), title and keyword is null
Example 3: If Date = Jan 1 and State is MO (Show row 1,2, and 4), title and keyword is null
Last example: if Keyword is Phone and everything else is null it shows row 3.
Is there a way to do this in Postgressql? It also would be convenient if the user didnt spell a state right but still pulled up similar results. Basically I will have a interface where a user will select a date, or title and/or state, or maybe just use a key word to filter the results
Your first task is to build a combined view of the tables involved supplying null for each that does not exit in a particular table. The following uses a CTE consisting of union of the 3 tables to accomplish that.
with combined as
(Select date1 as con_date
, split_part(location1, ',', 1) as city
, split_part(location1, ',', 2) as state
, title1 as title
, null as summary
from table_1
union all
select date2
, state
, null
, title2
, null
from table_2
union all
select date3
, null
, null
, title
, null
from table_3
)
select * from combined;
From there you can build a VIEW using the above then construct an appropriate query for the entered parameters. An alternative is a function that returns a table as below.
create or replace function search_combined(
search_date_in date default null
, search_title_in text default null
, search_state_in text default null
, search_word_in text default null
)
returns table (con_date date
, city text
, state text
, title text
, summary text
)
language sql
as $$
with combined as
(Select date1 as con_date
, split_part(location1, ',', 1) as city
, split_part(location1, ',', 2) as state
, title1 as title
, null as summary
from table_1
union all
select date2
, state
, null
, title2
, null
from table_2
union all
select date3
, null
, null
, title
, null
from table_3
)
select *
from combined
where 1=1
and (con_date = search_date_in or search_date_in is null)
and (state = search_state_in or search_state_in is null)
and (title = search_title_in or search_title_in is null)
and (title = search_word_in or search_word_in is null);
$$;
-- Test
select search_combined(search_date_in => date '2019-01-01');
or
select *
from search_combined(search_date_in => date '2019-01-01');
select *
from search_combned(search_date_in => date '2019-01-01'
,search_state_in => 'Mo'
);
select *
from search_combined( search_word_in => 'Phone');
The above should work as is, but I have not tested it as your sample data is a picture. In the future please provide sample data as text; as that allows copy/past to build it locally.

How to order UNPIVOT

I have the following UNPIVOT code and I would like to order it by the FactSheetSummary columns so that when it is converted to rows it is order 1 - 12:
INSERT INTO #Results
SELECT DISTINCT ReportingDate, PortfolioID,ISIN, PortfolioNme, Section,REPLACE(REPLACE(Risks,'‘',''''),'’','''')
FROM
(SELECT DISTINCT
ReportingDate
, PortfolioID
, ISIN
, PortfolioNme
, Section
, FactSheetSummary_1, FactSheetSummary_2, FactSheetSummary_3
, FactSheetSummary_4, FactSheetSummary_5, FactSheetSummary_6
, FactSheetSummary_7, FactSheetSummary_8, FactSheetSummary_9
, FactSheetSummary_10, FactSheetSummary_11, FactSheetSummary_12
FROM #WorkingTableFactsheet) p
UNPIVOT
(Risks FOR FactsheetSummary IN
( FactSheetSummary_1, FactSheetSummary_2, FactSheetSummary_3
, FactSheetSummary_4, FactSheetSummary_5, FactSheetSummary_6
, FactSheetSummary_7, FactSheetSummary_8, FactSheetSummary_9
, FactSheetSummary_10, FactSheetSummary_11, FactSheetSummary_12)
)AS unpvt;
--DELETE records where there are no Risk Narratives
DELETE FROM #Results
WHERE Risks = ''
SELECT
ReportingDate
, PortfolioID
, ISIN
, PortfolioNme
, Section
, Risks
, ROW_NUMBER() OVER(PARTITION BY ISIN,Section ORDER BY ISIN,Section,Risks) as SortOrder
FROM #Results
order by ISIN, Risks
Is it possible to do this? I thought the IN of the UNPIVOT would dictate the order? Do I need to add a column to dictate which I would like to be 1 through to 12?
Just use case expression to order:
order by case FactsheetSummary
when 'FactSheetSummary_1' then 1
when 'FactSheetSummary_2' then 2
when 'FactSheetSummary_12' then 12 end