SQL script problem under Oracle Fusion MiddleWare - Item Aggregation - sql
I am brand spanking new to SQL and Stack Overflow. I am originally an accountant but have recently moved on to financial analytics. I am having trouble understanding how to write SQL to aggregate manually created items under a single column:
Report Draft
From the report draft attached, you'll see there is multiple lines for both Fringe and Other Direct Expenses, I want to make these single lines, but have been trying for weeks with no other help.
Here is my code:
SELECT
subjectarea1.ProjectName saw_0,
subjectarea1.PurchaseOrderAmount saw_1,
subjectarea1.ProjectID saw_2,
subjectarea1.BeginDate saw_3,
subjectarea1.EndDate saw_4,
subjectarea1.Indirect saw_5,
subjectarea2.Location saw_6,
subjectarea2.BudgetID saw_7,
subjectarea2.budgetamount saw_8,
subjectarea2.BudgetAcount saw_9,
subjectarea1.Credit saw_10,
subjectarea1.Debit saw_11,
subjectarea1.GLaccount saw_12,
subjectarea1.Debit - subjectarea1.Credit saw_13,
subjectarea2.budgetamount - (subjectarea1.Debit - subjectarea1.Credit) saw_14,
subjectarea1.Account_Category saw_15,
subjectarea2.Account_Category2 saw_16,
REPORT_AGGREGATE("subjectarea1"."Debit"-"subjectarea1"."Credit" BY "subjectarea1"."Account_Category"),
REPORT_AGGREGATE("subjectarea2"."budgetamount"-("subjectarea1"."Debit"-"subjectarea1"."Credit") BY "subjectarea1"."Account_Category")
FROM (SELECT "gl:gl detail"."project"."SIHB:PROJECT_INDIRECT_RATE" Indirect,
"gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" GLaccount,
CASE WHEN "gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" IN ('45010','50010') THEN 'Direct Revenue' WHEN "gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" IN ('45020','50020') THEN 'Indirect Revenue' WHEN "gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" ='70010' THEN 'Salaries' WHEN "gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" IN ('70020','70030','70040','70045','70050','70055','70060','70070','70080','70090','70100','70110') THEN 'Fringe' WHEN "gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" BETWEEN '70120' AND '89999' THEN 'Other Direct (AP Expenses)' WHEN "gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" ='90000' THEN 'Indirect Expense' WHEN "gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" IN ('40010','40020','40030','40040','40050','41010','41020','41030','41040','41050','41060','43000','43010','44010','45030','45070','50030','51010','51015','51020','51030','51033','51035-001','51035-002','51035-003','51035-004','51035-005','51035-006','51035-007','51035-008','51035-009','51035-010','51035-011','51035-012','51035-013','51035-014','51035-015','51035-016','51035-017','51035-018','51035-019','51035-020','51035-021','51035-022','51035-023','51035-024','51035-025','51035-026','51035-060','51035-062','51040','51050','51060','51070','51075','52010','52020','53010','53020','53030','54010','54020','54030','58010','58020','59999') THEN 'Other Revenue Accounts' WHEN "gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" ='98010' THEN 'Capital Asset (Grant)' ELSE "gl:GL Detail"."General ledger detail Attributes"."ACCOUNTNO" END Account_Category,
"gl:gl detail"."Project"."name" ProjectName,
"gl:gl detail"."project"."poamount" PurchaseOrderAmount,
"gl:gl detail"."Project"."projectid" ProjectID,
"gl:gl detail"."project"."BEGINDATE " BeginDate,
"gl:gl detail"."General ledger detail Measures"."CREDITAMOUNT" Credit,
"gl:gl detail"."General ledger detail Measures"."DEBITAMOUNT" Debit,
"gl:gl detail"."project"."ENDDATE" EndDate
FROM "gl:GL detail") subjectarea1 left outer join (SELECT "gl:GL Budget"."GL budget Attributes"."BUDGETID" BudgetID,
"gl:GL Budget"."Project"."Locationname" Location,
"gl:GL Budget"."GL budget Measures"."AMOUNT" budgetamount,
"gl:GL Budget"."GL budget Attributes"."ACCT_NO" BudgetAcount,
CASE WHEN "gl:GL Budget"."GL budget Attributes"."ACCT_NO" IN ('45010','50010') THEN 'Direct Revenue' WHEN "gl:GL Budget"."GL budget Attributes"."ACCT_NO" IN ('45020','50020') THEN 'Indirect Revenue' WHEN "gl:GL Budget"."GL budget Attributes"."ACCT_NO" ='70010' THEN 'Salaries' WHEN "gl:GL Budget"."GL budget Attributes"."ACCT_NO" IN ('70020','70030','70040','70045','70050','70055','70060','70070','70080','70090','70100','70110') THEN 'Fringe' WHEN "gl:GL Budget"."GL budget Attributes"."ACCT_NO" BETWEEN '70120' AND '89999' THEN 'Other Direct (AP Expenses)' WHEN "gl:GL Budget"."GL budget Attributes"."ACCT_NO" ='90000' THEN 'Indirect Expense' WHEN "gl:GL Budget"."GL budget Attributes"."ACCT_NO" IN ('40010','40020','40030','40040','40050','41010','41020','41030','41040','41050','41060','43000','43010','44010','45030','45070','50030','51010','51015','51020','51030','51033','51035-001','51035-002','51035-003','51035-004','51035-005','51035-006','51035-007','51035-008','51035-009','51035-010','51035-011','51035-012','51035-013','51035-014','51035-015','51035-016','51035-017','51035-018','51035-019','51035-020','51035-021','51035-022','51035-023','51035-024','51035-025','51035-026','51035-060','51035-062','51040','51050','51060','51070','51075','52010','52020','53010','53020','53030','54010','54020','54030','58010','58020','59999') THEN 'Other Revenue Accounts' WHEN "gl:GL Budget"."GL budget Attributes"."ACCT_NO" ='98010' THEN 'Capital Asset (Grant)' ELSE "gl:GL Budget"."GL budget Attributes"."ACCT_NO" END Account_Category2,
"gl:GL Budget"."Project"."PROJECTID" ProjectIDD FROM "gl:GL Budget") subjectarea2 ON (subjectarea1.ProjectID = subjectarea2.ProjectIDD) AND (subjectarea1.GLaccount = subjectarea2.BudgetAcount)
WHERE
(subjectarea2.BudgetID = 'Budget') AND (subjectarea1.ProjectID = '131-20') AND (subjectarea1.GLaccount BETWEEN '70010' AND '90000') AND (subjectarea2.BudgetAcount BETWEEN '70010' AND '90000')
ORDER BY saw_0, saw_1, saw_2, saw_3, saw_4, saw_5, saw_6, saw_7, saw_9, saw_12
Anyone know what im doing wrong here?
I tried to create an aggregate within an aggregate, but found that is not possible with oracle fusion middleware. Also, I understand that this is probably a simple problem for many, but I've gotten desperate. Any help is much appreciated!
This is not really an answer, but I recognize SQL generated by what used to be called Siebel Analytics Warehouse, then Oracle Business Intelligence, and just Oracle Fusion, I guess. Great tool until you have to really understand what's going on, and then it's hell on earth to try to fix what seem like minor problems.
I have a lot of sympathy for your problem, so let me first ask if you generated this SQL yourself through the OBIEE front end tool (Create Analysis) or did you inherit this SQL from someone else generating it in the tool? Because if you generated it yourself, the best thing you can do is go back to the tool you generated it in and look for something called "Aggregation Rules" and go add some for this query. (It's been a lot of years since I've used OBIEE and supported this tool, so forgive me if I'm not too specific here. I just don't remember the details of writing queries in it.)
Your problem here is that no part of your query is aggregating anything together. This means you are getting one report line for every record in your data base. When you turn on aggregation correctly, it will start summing up your measures across your attributes. But remember, the more attributes in your query the finer the level of detail in the number of rows. If you want one number for each category, then category needs to be your sole attribute in your query. There are ways to turn your other report attributes into measures, but you'll want to think about what do I want to show when, for example, I'm aggregating multiple budget line item names within a single category.
Since you're a complete SQL newbie, let me leave you with this simple primer and a really high level analysis of what OBIEE thinks it's doing to give you your results:
SQL queries are all keyword-driven, and the keywords must appear in a fixed order. They ALL start with SELECT followed by a list of table columns and calculations to be included in your results. An example of such a calculation in your query issubjectarea1.Debit - subjectarea1.Credit. The next keyword is FROM followed by a list of tables connected by their join relationship. Your OBIEE administrator created these table relations when he/she defined the subject area. One table your query references is "gl:GL Budget". The next keyword is WHERE followed by a set of filter expressions to only include the appropriate raw data. Your WHERE filter contained the clause subjectarea1.ProjectID = '131-20' indicating your report was for only one project, 131-20. The next keyword is GROUP BY followed by a list of the columns you want to aggregate by. Since there was no Group By in your query I could tell that there was no aggregation so you're getting all the detail that's available. Lastly you have ORDER BY followed by a list of columns to order the record display by.
At a really high level your query is doing something like this:
SELECT <some stuff separated by commas>
FROM (
SELECT <other stuff>
FROM "gl:GL Budget"
) Left Outer Join ( <1st half of relationship spec>
SELECT <more stuff>
FROM gl:GL Budget"
) On (subjectarea1.ProjectID = subjectarea2.ProjectIDD) AND (subjectarea1.GLaccount = subjectarea2.BudgetAcount)
WHERE (BudgetID = 'Budget') AND (ProjectID = '131-20')
ORDER BY <your first seven columns & ninth & twelfth>
Once you get the aggregation rules sorted out, I would expect to see a Group By section get added in.
Hope this helps. Like the tape recorder said in Mission Impossible, "Good Luck, Jim".
Related
How to convert SQL statement to equivalent Cognos query calc?
I was building a crosstab like so: and need to instead convert into a list. The part that's giving me trouble is converting the grouping of v_IT or BU which feeds down into Act and Direct Cost into 4 separate fields for the list which would be 'IT Act', 'IT Direct Cost', 'BU Act', and BU Direct Cost.' I'm not sure how to make a calculation for these fields using those two data items. I think the SQL would be something like: Select Act$ from 'mytable' where v_ITorBU = 'IT' for the first 'IT Act' data item at least. v_IT or BU has two values 'IT', and 'BU'. I tried Case When v_ITorBU = 'IT' then act$ end but this only gives me the overall act values, not those specifically for IT. I need the specific IT actuals as well as the BU actuals. Does anyone have any insight on how to make this into Cognos query calculations?
The grouping of v_IT or BU which feeds down into Act and Direct Cost into 4 separate fields for the list which would be 'IT Act', 'IT Direct Cost', 'BU Act', and BU Direct Cost. Go to the query add data items from the tool box Create the definition expression, for example this would be for [IT Act] IF( [v_IT or BU] = 'IT Act' )Then([Act$])Else(0) Repeat this process for IT Direct Cost BU Act BU Direct Cost Also repeat these 4 data items for the cost metric Remember to check the properties in order to achieve the correct aggregation
Here is the SQL. select [Budget Category] , [v_Cost Cat Consolidation] , sum(case when [v_IT or BU] = 'IT' then [Act $] else 0 end) as 'IT Act' , sum(case when [v_IT or BU] = 'IT' then [Direct Cost] else 0 end) as 'IT Direct Cost' , sum(case when [v_IT or BU] = 'BU' then [Act $] else 0 end) as 'BU Act' , sum(case when [v_IT or BU] = 'BU' then [Direct Cost] else 0 end) as 'BU Direct Cost' from MyTable where {somefilters} group by [Budget Category] , [v_Cost Cat Consolidation] So a data item expression in Cognos may look like ... case when [v_IT or BU] = 'IT' then [Act $] else 0 end ...and you'll want to be sure to use the Total aggregate function on it. If you have done that and the numbers are not looking right, please add some detail to the problem statement. This can also be done using the IF-THEN-ELSE methodology proposed by hnoel.
Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY
I was looking for help in the error I get in SQL Server when I try run this query. The query is just for splitting the products to 4 groups by 2 conditions (the quantity and the revenue). For the revenue I need the SUM function, and that's causing me problems in the GROUP BY (if I understood the error well). How can I solve this problem? Select CASE WHEN Ord1.Quantity<10 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<50000 THEN 'Risky Product' WHEN Ord1.Quantity<30 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<250000 THEN 'Fair Product' WHEN Ord1.Quantity<60 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<750000 THEN 'Normal Product' Else 'Great Product' End As 'Group', SUM(Ord1.Quantity*Ord1.UnitPrice) From (Select OD.ProductID,OD.Quantity,OD.UnitPrice From [Order Details] As OD INNER JOIN Orders As O ON O.OrderID=OD.OrderID Where DATEPART(YEAR,O.OrderDate)=1997) As Ord1 Group By CASE WHEN Ord1.Quantity<10 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<50000 THEN 'Risky Product' WHEN Ord1.Quantity<30 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<250000 THEN 'Fair Product' WHEN Ord1.Quantity<60 OR SUM(Ord1.Quantity*Ord1.UnitPrice)<750000 THEN 'Normal Product' Else 'Great Product' End
You have confirmed my suspicion. And I'll respond with - no point in correcting a query that is logically flawed at the beginning. You need to aggregate BEFORE you categorize. Your original approach was attempting to do both. So start over. Typically it is easier to break your problem into pieces that can be accomplished - you start at the basic level of just selecting rows, then you modify that code step-by-step to build the logic that will achieve your goal. That's appropriate for any language. So here is my shot at an abbreviated solution. Since you did not provide a schema or data, I used AdventureWorks. In the future, help is more likely to be provided and useful when you provide schema and data or use a standard sample database. with cte as ( select det.ProductID, sum(det.OrderQty * det.UnitPrice) as totalvalue from Sales.SalesOrderDetail As det where exists ( select * from Sales.SalesOrderHeader as ord where det.SalesOrderID = ord.SalesOrderID and ord.OrderDate >= '20130101' and ord.OrderDate < '20140101' ) group by det.ProductID ) select cte.ProductID, cte.totalvalue, case when totalvalue >= 75000 then 'Great Product' else 'meh - needs work' end as [Group] from cte order by [Group], cte.ProductID ; Pay attention to the where clause in the cte. It is better to avoid applying a function to a column when using that as a filter since a function will prevent the use of any helpful indexes. Note also that I left out most of your logic. This demonstrates the technique; you will need to expand it for your actual needs.
Need MS Access Form Field to automatically Calculate and Allocate Costs based on given Parameters
Below is my mock database that I am using. I have four different tables: Tbl_MainDatabase, Tbl_InsuranceCoverage, Tbl_MatterDetail, and Tbl_PaymentProcessing. What I want - I want my form to determine the remaining Retention Limit (i.e., Retention Limit for the applicable policy - sum of invoices for the same Claim Number ) According to the mock database, the required answer should be [ $2500 - (300+700+355)] as highlighted for your convenience What I tried I used the help of Graphical representation through the following query: SELECT [Claim Number], Sum([Net Invoice Amount]) FROM [PaymentProcessing] GROUP BY [Claim Number] This method works to show me how much I spent per claim number so far in the form of a graph. However I want to display the remaining amount. Any Help is appreciated :) I am one month old at using Access. But I am trying my best to learn Thank you in advance!
SELECT IC.[Retention Limit]-SUM([Net Invoice Amt]) AS Remaining, MD.[Claim Number], IC.[Retention Limit], IC.InsuranceID FROM tbl_InsuranceCoverage IC INNER JOIN tbl_MatterDetail MD ON ic.InsuranceID = MD.Policy INNER JOIN tbl_PaymentProcessing PP ON MD.MatterDetailID=pp.MatterDetailID AND MD.[Claim Number]=pp.[Claim Number] GROUP BY MD.[Claim Number], IC.[Retention Limit], IC.InsuranceID See if this works. Havent tested it but seems simple. You can remove the extra columns, but this will hlep you understand joins a bit
For All the New users The above code by #Doug Coats works perfectly. Make Sure All the Foreign Key and Primary Keys is linked in the Relationship Property. ( One of the way To do this in the Query is - Right click on the Query and select Design View --> Right click again on the grey space and Select Show all Tables Now Drag your Primary Key of the table and drop at the foreign Key on the other table --> This will create a relationship between both for the Query Purpose. This will also Prevent Data from Duplication in the query then use a similar code as described by Doug Coats in the above comment in the SQL View SELECT [Insurance Coverage].[Retention Unit]-Sum([Net Invoice Amount]) AS Remaining, [Matter Detail].[Claim Number], [Insurance Coverage].[Retention Unit], [Matter Detail].Policy FROM (([Main Database] INNER JOIN [Matter Detail] ON [Main Database].[Database ID] = [Matter Detail].[Short Name]) INNER JOIN [Payment Processing] ON ([Matter Detail].[Matter Detail ID] = [Payment Processing].[Matter Detail ID]) AND ([Main Database].[Database ID] = [Payment Processing].[Short Name])) INNER JOIN [Insurance Coverage] ON [Matter Detail].Policy = [Insurance Coverage].[Insurance ID] GROUP BY [Matter Detail].[Claim Number], [Insurance Coverage].[Retention Unit], [Matter Detail].Policy; You can then display this query in the form - I am still evaluating best way to display this query probably in a Combo Box (Not sure if any other controls has a row source) Thank you
Error in SQL Server CTE statement
I believe I'm writing this CTE wrong, I'm a major novice with this so explain as much as you can. Still getting the can not be bound error on almost everything Error messages: The multi part identifier could not be bound "PS_Margin.Emp or Vendor ID The multi part identifier could not be bound "PS_Margin.Project Profit by Person % Issues/ Goals: Possible need to add aliases to column names with spaces and special characters although I don't know how to do this WITH Profit_Score_CTE ( [Emp or Vendor ID], [Project Profit by Person %] ) AS ( SELECT PS_Margin.[Emp or Vendor ID], CASE WHEN ps.[Project Profit by Person %] > .4 THEN 1 WHEN ps.[Project Profit by Person %] > .2 THEN 3 WHEN ps.[Project Profit by Person %] > .1 THEN 5 WHEN ps.[Project Profit by Person %] > .05 THEN 8 ELSE 13 END AS [Profit Score] FROM dbo.PS_Margin AS ps ) SELECT emp.[Employee Name], emp.[USID], [Profit Score]*0.3 AS [Final Score] FROM dbo.PS_Emp AS emp left join Profit_Score_CTE ON emp.USID = Profit_Score_CTE.[Emp or Vendor ID]
"Cannot be bound" usually refers to how you are ID'ing columns with a table alias. Try giving your table an alias and using that for the columns: WITH --Section 1: Profit Score Profit_Score_CTE( [Emp or Vendor ID], [Project Profit by Person %] ) AS ( SELECT PS_Margin.[Emp or Vendor ID], CASE WHEN ps.[Project Profit by Person %] > .4 THEN 1 WHEN ps.[Project Profit by Person %] > .2 THEN 3 WHEN ps.[Project Profit by Person %] > .1 THEN 5 WHEN ps.[Project Profit by Person %] > .05 THEN 8 ELSE 13 END AS [Profit Score] FROM [dbo].[PS_Margin] ps )
I'm guessing because you haven't provided enough information to reproduce the error. But I think the problem might be that you define the columns of your CTE here: Profit_Score_CTE( [Emp or Vendor ID], [Project Profit by Person %] ) AS ( And yet you alias your second column with a different name here: AS [Profit Score] You need to decide which column name you want your CTE to expose and use it consistently.
I'll assume your CTE is correctly defined. Your cte is named "Profit_Score_CTE". Your actual select statement refers to objects dbo.PS_Emp and dbo.PS. I'll guess that you should replace dbo.PS with your CTE name. E.g., with Profit_Score_CTE as (select ...) select emp.[Employee Name], ... from dbo.PS_Emp as emp left join Profit_Score_CTE on emp.USID = Profit_Score_CTE.[Emp or Vendor ID] order by ... ; The alias PS is visible only inside the definition of the CTE. It cannot be used in the actual select statement that uses your CTE. Notice that I gave your table an alias and used it - a consistent coding style is something you should strive to achieve. Also notice the order by clause. Rows within a resultset have no defined order without one - and usually it is important. And PLEASE use white space to make your code readable and to avoid easy mistakes. You crammed everything together in the formula for computed column [Final Score].
Thanks all for your help! My newbie ribbon was really showing with this one. The problem had nothing to do with SQL at all. I wasn't pointing to the correct database in sql server. In the available databases drop down box on the top left hand screen of SQL Server you need to select the database you're working from. This will enable the script to find your database, and begin to solve alot of the errors.
SQL Create View - Sum Transactions on one line
I want to create a view, whereby all post stock transactions will post on one line, as per my SQL Statement below, I get all transactions, but each is on a new line. I want the arrangement to be each new stock item on a new line, with "QtyOnHand" as the next column. Then I need all the QtyOut transactions to sum up in one column and all QtyIn to sum in another. Is this possible? SELECT StkItem.ItemGroup ,StkItem.Qty_On_Hand AS QtyOnHand ,PostST.TrCodeID ,PostST.Description ,PostST.Quantity ,PostST.Reference ,PostST.Order_No ,PostST.fQuantityInvoiced ,PostST.QuantityR ,PostST.TxDate ,PostST.Debit ,PostST.Credit ,Concat(StkItem.Description_1, ' - ',StkItem.Code) AS ItemAndCode FROM PostST INNER JOIN StkItem ON StkItem.StockLink = PostST.AccountLink The below picture shows how this statement currently shows - you can see on the far right how the same stock code is repeated for each transaction, as I would rather the stock item show once, and the transactions be summed. This data will be dumpted into Excel and then used to create a stock turnover report. Thank you!
You have to use SUM() and GROUP BY. Maybe that is what you need SELECT StkItem.ItemGroup ,SUM(StkItem.Qty_On_Hand) AS QtyOnHand ,PostST.TrCodeID ,PostST.Description ,SUM(PostST.Quantity) as Quantity ,PostST.Reference ,PostST.Order_No ,SUM(PostST.fQuantityInvoiced) as fQuantityInvoiced ,SUM(PostST.QuantityR) as QuantityR ,PostST.TxDate ,SUM(PostST.Debit) as Debit ,SUM(PostST.Credit) as Credit ,Concat(StkItem.Description_1, ' - ',StkItem.Code) AS ItemAndCode FROM PostST INNER JOIN StkItem ON StkItem.StockLink = PostST.AccountLink GROUP BY StkItem.ItemGroup ,PostST.TrCodeID ,PostST.Description ,PostST.Reference ,PostST.Order_No ,PostST.TxDate ,StkItem.Description_1 ,StkItem.Code