Need to return max value using case in subquery - max

I have records with several line items. I need to return the record and the max value of a flag that reviews the line items. A simplified version of the code without getting the max value for the flag is:
Select nvl(order.order_value, order2.order_value) as "order",
case when item.item_no in ('abc','def','ghi') then 'Y' else 'N' end as "Flag",
field 3,
field 4
from order
left join order2 on order.order_value=order2.order_value
left join item on item.order_value=order.order_value
The actual current code does have a lot of other fields selected from other various tables/subqueries.
My issue is that there are multiple items in the item table per order_value, and I only want one line per order. I want the flag to say yes if any item falls in the my 'y' list.

Related

Oracle counting distinct rows using two columns merged as one

I have one table where each row has three columns. The first two columns are a prefix and a value. The third column is what I'm trying to get a distinct count for columns one/two.
Basically I'm trying to get to this.
Account
Totals
prefix & value1
101
prefix & value2
102
prefix & value3
103
I've tried a lot of different versions but I'm basically noodling around this.
select prefix||value as Account, count(distinct thirdcolumn) as Totals from Transactions
It sounds like you want
SELECT
prefix||value Account,
count(distinct thirdcolumn) Totals
FROM Transactions
GROUP BY prefix, value
The count(distinct thirdcolumn) says you want a count of the distinct values in the third column. The GROUP BY prefix, value says you want a row returned for each unique prefix/value combination and that the count applies to that combination.
Note that "thirdcolumn" is a placeholder for the name of your third column, not a magic keyword, since I didn't see the actual name in the post.
If you want the number of rows for each prefix/value pair then you can use:
SELECT prefix || value AS account,
COUNT(*) AS totals
FROM Transactions
GROUP BY prefix, value
You do not want to count the DISTINCT values for prefix/value as if you GROUP BY those values then different values for the pairs will be in different groups so the COUNT of DISTINCT prefix/value pairs would always be one.

How can I display Row Number in Cross-Tab?

I'm looking for a way to display row number in my cross-tab.
I tried searching online for the answer on how to do it but I haven't found anything useful.
So I'm turning to the good people on Stack Overflow.
The reason that I want to do this, if it's even possible, is because many clients in the company I started working at asked to have a row number in the cross-tab.
I am using Visual Studio 2013 and Crystal Reports.
So is there any basic ( easy ) way to do this in Crystal Reports?
For example, I have a cross-tab that displays unit of measure and amounts.
https://imgur.com/a/lOjCq
But I would like my cross-tab to be like:
Amount
1. Total -38
2. KG
3. kut 9
4. LIT. 4
5. m -32
6. proc
7. KoŠ¼ -19
Please keep in mind that I only started working with Crystal Reports this week, so this is all new to me. And the cross-tab in the picture is just a random one I made to explain what I need.
Thank You in advance.
In order to show Row Number in your CrossTab you will need to first put Row Number in the Stored Procedure that sends data to your report.
In order to understand it better i will first show you how my data looks before i add a Row number(Pic 1).
Code:
select
a.S_ID as ID,
osn.sifra as BasicGoodsCode,
osn.naziv as BasicGoods,
null,
a.RobaSifra as GoodsCode,
a.Roba as Goods,
a.Detalj as Detail,
a.DetaljDodatak as DetailsAddon
from NP_Stavke s
left join RobaGrupe osn on osn.id = s.RobaId
left join #A a on a.S_ID = s.Id
order by BasicGoodsCode, ID
Pic 1: As you can see I have 3 different Ids for BasicGoods which means that I have 3 Rows in my CrossTab
Columns ID, BasicGoodsCode and BasicGoods are going to be Rows in my CrossTab.
Values from column DetailsAddon are going to be my columns in CrossTab.
Columns GoodsCode, Goods and Detail are going to be values in my CrossTab.
Column Pieces is not important.
Now that you know how everything looks we can start with adding a Row Number to our CrossTab.
Step 1:
First thing that you need to do is to add a Row number in table in your stored procedure.
To do this I used DENSE_RANK()
depending on your data you might need to use ROW_NUMBER() or maybe even something else. I used DENSE_RANK() because I needed my row number to change once S_ID changes.
Code:
select
a.S_ID as ID,
DENSE_RANK() OVER (ORDER BY osn.sifra, s.Id asc) as BasicGoodsRowNo, // THIS IS ADDED
osn.sifra as BasicGoodsCode,
osn.naziv as BasicGoods,
null as Pieces,
a.RobaSifra as GoodsCode,
a.Roba as Goods,
a.Detalj as Detail,
a.DetaljDodatak as DetailsAddon
from NP_Stavke s
left join RobaGrupe osn on osn.id = s.RobaId
left join #A a on a.S_ID = s.Id
order by BasicGoodsCode, ID
Lets take a look at how our data looks now(Pic 2)
As you can see we added a Row Number that changes when Id changes.
IMPORTANT: Row Number has to be ether Integer or Decimal in the DataTable that you are using in your report if it's not it will not work correctly.
Step 2:
We've done the 'hard' part now it's time to put Row number in our CrossTab.
When you create a CrossTab or when right click CrossTab and then click on 'Cross-Tab Expert...' it will open a window like this one and in it in the Row section you will insert your Row Number Column(in my case and as you can see in the code above the name of my Row Number Column is 'BasicGoodsRowNo').
Step 3:
Since you don't want to show only the Row number in the report left click on your Row and then click on 'Group Options...'(Pic 4)
Once the new window appears click on 'Options' tab then check the 'Customise group name field' then click on 'Use a formula as group name' and then on 'x-2'(Pic 5)
Step 4:
Enter a formula like this one:
toText( {myTbl.BasicGoodsRowNo}, 0, "" ) + '. ' + {myTbl.BasicGoodsCode} + ' ' + {myTbl.BasicGoods}
Of course your formula will not be exactly like mine since you will not have the same columns as I do. The only part of this formula that you HAVE to have is toText( {myTbl.BasicGoodsRowNo}, 0, "" ) where instead of {myTbl.BasicGoodsRowNo} you will put your row number column. You will need toText since if you dont have that and you want to show a String after your Row Number it will give you an error because RowNumber is an integer field.
GJ YOU ARE ALL DONE AND IT WASN'T THAT HARD WAS IT
How My CrossTab looks once RowNumber is added
Now there is a way to simplify this process and that is:
Step 1:
In your stored procedure create 2 columns. One will show Row Number and the other will show Value that will be displayed as CrossTab row.
Code:
select
a.S_ID as ID,
DENSE_RANK() OVER (ORDER BY osn.sifra, s.Id asc) as BasicGoodsRowNo, // RowNumber
CONVERT(varchar(10), DENSE_RANK() OVER (ORDER BY osn.sifra, s.Id asc)) + '. ' + osn.sifra + ' ' +osn.naziv as BasicGoods, // Value that will be displayed in CrossTab Row
null as Pieces,
a.RobaSifra as GoodsCode,
a.Roba as Goods,
a.Detalj as Detail,
a.DetaljDodatak as DetailsAddon
from NP_Stavke s
left join RobaGrupe osn on osn.id = s.RobaId
left join #A a on a.S_ID = s.Id
order by BasicGoods, ID
As you can see Column BasicGoodsRowNo did not change and will still display the same values as before and I have deleted the clumns BasicGoodsCode and BasicGoods and replaced them with this
CONVERT(varchar(10), DENSE_RANK() OVER (ORDER BY osn.sifra, s.Id asc)) + '. ' + osn.sifra + ' ' +osn.naziv as BasicGoods,
The BasicGoods column will show BasicGoodsRowNo + BasicGoodsCode + BasicGoods.
Step 2:
Step 2 is the same as before.
Step 3:
Once you click on your row and on 'Group Options' go to 'Options' tab again then check the 'Customise group name field' check box again and after that instead clicking on 'Use a formula as group name' click on 'Choose from existing field' and from a combo box select the column you want to show as Row Value in your CrossTab. In my Case that is 'BasicGoods' column (Pic 7).
I used the first method since depending on what user decides I may not show CrossTab at all and I may not show BasicGoods but if you only have CrossTab in your report you can use the second, shorter and easier, method.
If you have any questions feel free to ask.

SSRS - exclude hidden values from sum

I did not hide the entire rows. I hid just the duplicated values in one column and I need to sum that same column, excluding the hidden values. Thank you very much.
The field having duplicated values that I wanted to hide is SpaceArea This is how I hid the duplicated values from rows on the SpaceArea column:
=IIF(Fields!SpaceID.Value = Previous(Fields!SpaceID.Value),True, False)
Then I need to SUM all the SpaceArea excluding the hidden values.
Once I tried to use the same Show/Hide logic to the Sum expression as per another post of yours, I got an error message. This is what I tried:
=Sum(IIF(Fields!SpaceID.Value = Previous(Fields!SpaceID.Value), Nothing, Fields!SpaceArea.Value))
==> then I got this error message:
previous functions cannot be specified as nested aggregates.
You can use row_number() in your SQL to highlight the duplicates.
row_number() over (partition by SpaceID order by (select null)) as [RowNumber]
This will give you an arbitrary numbering to the duplicate rows.
Then in SSRS you can use..
sum(iif(Fields!RowNumber.Value = 1, Fields!SpaceArea.Value, Nothing)) to only sum the first instance of each duplicate.

How to sort rows in "SELECT ... FOR ALL ENTRIES ...", ORDER BY is not accepted

I am selecting a table that has multiple of the same records (same REQUEST_ID) with different VERSION_NO. So I want to sort it descending so I can take the highest number (latest record).
This is what I have...
IF it_temp2[] IS NOT INITIAL.
SELECT request_id
version_no
status
item_list_id
mod_timestamp
FROM ptreq_header INTO TABLE it_abs3
FOR ALL ENTRIES IN it_temp2
WHERE item_list_id EQ it_temp2-itemid.
ENDIF.
So version_no is one of the SELECT field but I want to sort that field (descending) and only take the first row.
I was doing some research and read that SORT * BY * won't work with FOR ALL ENTRIES. But that's just my understanding from reading up.
Please let me know how I can make this work. Thanks
You can simply sort the itab after the select and delete all adjecent duplicates afterwards, if wanted:
SORT it_abs3 BY request_id [ASCENDING] version_no DESCENDING.
DELETE ADJACENT DUPLICATES FROM it_abs3 COMPARE request_id.
Depending on the amount of expected garbage (to be deleted lines) in the itab an SQL approach is better. See Used_By_Already's answer.
If you are using the term "latest" to indicate "the most recent entry", then the field mod_timestamp appears to be relevant and you could use it this way to choose only the most recent records for each request_id.
SELECT
request_id
, version_no
, status
, item_list_id
, mod_timestamp
FROM ptreq_header h
INNER JOIN (
SELECT
request_id
, MAX(mod_timestamp) AS latest
FROM ptreq_header
GROUP BY
request_id
) l
ON h.request_id = l.request_id
AND h.mod_timestamp = l.latest
If you want the largest version_no, then instead of MAX(mod_timestamp) use MAX(version_no)
Just declare the it_abs3 as a sorted table with key that would consist of the columns you want to sort by.
You can also sort the table after the query.
SORT it_abs3 BY ...

Stacked column Flash chart counting all values

I am building stacked column flash chart on my query. I would like to split values in column for different locations. For argument sake I have 5 ids in location 41, 3 ids in location 21, 8 ids in location 1
select
'' link,
To_Char(ENQUIRED_DATE,'MON-YY') label,
count(decode(location_id,41,id,0)) "location1",
count(decode(location_id,21,id,0)) "location2",
count(decode(location_id,1,id,0)) "location3"
from "my_table"
where
some_conditions = 'Y';
as a result of this query Apex is creating stacked column with three separate parts( hurray!), however it instead of having values 5,3 and 8, it returns three regions 16,16,16. ( 16 = 5 +3+8).
So obviously Apex is going through all decode conditions and adding all values.
I am trying to achieve something described in this
article
Apex doesn't appear to be doing anything funky, you'd get the same result running that query through SQL*Plus. When you do:
count(decode(location_id,41,id,0)) "location1",
.. then the count gets incremented for every row - it doesn't matter which column you include, and the zero is just treated as any fixed value. I think you meant to use sum:
sum(decode(location_id,41,1,0)) "location1",
Here each row is assigned either zero or one, and summing those gives you the number that got one, which is the number that had the specified id value.
Personally I'd generally use caseover decode, but the result is the same:
sum(case when location_id = 41 then 1 else 0 end) "location1",

Resources