crystal reports group name formula using a record from a different line in table - crystal-reports

I am trying to create a group name formula using a record from a different line in the table than the line that the records contained in this group are linked to.
First off, my data has the word group in it, so to avoid confusion I have italicized it to differentiate it from groups in Crystal Reports.
My table that I am pulling the records for this group name from has:
{GroupSection.Group} Groups of items in our inventory database
{GroupSection.Section} Sections (these are like subgroups nested within each inventory group).
{GroupSection.Description} The problems start here because the descriptions for {GroupSection.Group} and {GroupSection.Section} are both stored here.
This is a sample of my table:
{GroupSection.Group} {GroupSection.Section} {GroupSection.Description}
3.00 0.00 PRECAST CONCRETE PRODUCT
3.00 50.00 MISC PRECAST CONCRETE PRODUCT
3.00 99.00 *Z* MISC PRECAST CONCRETE PRODUC
4.00 0.00 CEMENT SUPPLIES
4.00 50.00 MISC CEMENT SUPPLIES
4.00 99.00 *Z* MISC CEMENT SUPPLIES
The first and fourth line in this table are descriptions for {GroupSection.Group} (they have a 0.00 in the {GroupSection.Section} line) and the rest are descriptions for {GroupSection.Section}. The actual data that is contained in this report is in a different table and has the same two fields as the first two in this table, but not the third field, hence the need to link to and use this table to make the descriptions of the group names. The other table has no records that link to the lines with 0.00.
I want my Group Tree to look like this:
3. PRECAST CONCRETE PRODUCT
50 MISC PRECAST CONCRETE
99 *Z* MISC PRECAST CONCRETE
4. CEMENT SUPPLIES
50 MISC CEMENT SUPPLIES
99 *Z* MISC CEMENT SUPPLIES
This is the flawed formula I am using now in the Group Name formula for the top group:
ToText (left(Cstr({GroupSection.Group}),2))+ " " + ToText (If {GroupSection.Section} <> 0 then {GroupSection.Description} Else " ")
This is the Group Name formula for the inner nested group (working fine):
ToText (left(Cstr({GroupSection.Section}),2))+ " " + ToText ({GroupSection.Description})
This is what my Group Tree looks like now:
3. MISC PRECAST CONCRETE
50 MISC PRECAST CONCRETE
99 *Z* MISC PRECAST CONCRETE
4. MISC CEMENT SUPPLIES
50 MISC CEMENT SUPPLIES
99 *Z* MISC CEMENT SUPPLIES
As you can see, I need to get the name for the outer group from the first row in the table even though it's linking the records that are in the group to the second and third row in the table. Make sense?
I have tried using previous() in the formula but it gives the following error: This function cannot be used because it must be evaluated later.
Edit: I also just tried adding the same table again and linking it once to the group and once to the section and it worked for the group names, but now I have 1.9 million records, something really duplicated. So that won't work unless I can figure out how to fix the multiple records.
The "." in the group name description is an unrelated problem. It's the best I can do to get 3.00 to display as 3 and 50.00 to display as 50.
Thanks for any help!
Edit Dec 30, 2013 for user #Promethean:
Sorry I am new at SQL Command Tables. I took a command table from another report and did some changes to it. This is how far I got:
SELECT
"GroupSection"."Group",
"GroupSection"."Section",
"GroupSection"."Description"
FROM ("SpruceDotNet"."dbo"."InventoryCommon" "InventoryCommon" with (nolock)
INNER JOIN
"SpruceDotNet"."dbo"."GroupSection" "GroupSection" with (nolock)
ON "InventoryCommon"."Group"="GroupSection"."Group")
WHERE
"GroupSection"."Section"=0
ORDER BY
"InventoryCommon"."Group"
Is there any chance you could use this info to modify your command table so a dummy like me can follow it? It looks like you are adding one of the fields twice, but I don't follow everything.
And then how would you join the command table to the bigger table that contains the more detailed? I would have to use the right kind of join so I don't end up duplicating the records?
Any help is greatly appreciated.

This may be very straightforward if you do this with SQL in a commmand table:
select a.Group, a.Section, a.Description,
b.GroupName
from GroupSection a
left outer join
(
select concat( format(b.Group, 0), '. ', a.Description) as GroupName, b.Group
from GroupSection b
where b.Section = 0
) c
on a.Group = b.Group
The concat may change depending on your database provider. This reflects MySQL. perforing this against a table that reflects your sample data would produce the following:
{GroupSection.Group}|{GroupSection.Section}|{GroupSection.Description} |{GroupSection.GroupName}
3.00 | 0.00 | PRECAST CONCRETE PRODUCT | 3. PRECAST CONCRETE PRODUCT
3.00 | 50.00 | MISC PRECAST CONCRETE PRODUCT | 3. MISC PRECAST CONCRETE PRODUCT
3.00 | 99.00 | *Z* MISC PRECAST CONCRETE PRODUC| 3. *Z* MISC PRECAST CONCRETE PRODUC
4.00 | 0.00 | CEMENT SUPPLIES | 4. CEMENT SUPPLIES
4.00 | 50.00 | MISC CEMENT SUPPLIES | 4. MISC CEMENT SUPPLIES
4.00 | 99.00 | *Z* MISC CEMENT SUPPLIES | 4. *Z* MISC CEMENT SUPPLIES
This can easily be grouped in Crystal to produce your desired results.
BEGIN EDITS:
Check this out. It's a working SQLfiddle using your table structure. Only GroupSection is necessary to accomplish this part, so I ignored the other. You can play around with different queries to see what hapens, but as-is it will pass to Crystal the necessary derived field to group on in Crystal. You'll need to still group on the new field, GroupName, in Crystal.
As for the other tables, you can treat the command table the same way you any other table. Just make sure you add key/linking field to the command if its not there in your mockup.
Here's the fiddle: http://sqlfiddle.com/#!2/aa88d/5/0
and just in case the comments there make it too confusing to see the code, here it is with my annotations stripped out:
SELECT gs2.GroupName,
gs.sGroup, gs.Section, gs.Description
FROM GroupSection gs
left outer join
(
SELECT concat( format(inn.sGroup, 0), '. ', inn.Description) as GroupName, inn.sGroup
FROM GroupSection inn
WHERE inn.Section = 0
) gs2
ON gs.sGroup = gs2.sGroup

This is quite a handful! It seems that your problem is in the database, as you pointed out at the beginning.
If you group by {GroupSection.Group} and put the {GroupSection.Description} in the Group Header next to it, you should get 3. MISC PRECAST CONCRETE. And then you put {GroupSection.Section} in the Detail Section and {GroupSection.Description} next to it, you should get 50 MISC PRECAST CONCRETE. So at this point I would not use a formula to group by, but use the fields. So only one group ({GroupSection.Group}) and the rest in the Detail Section. Please try that suggestion and llet me know how that works.
EDIT:
I don't think it's going to work. Because everything is in the same table you will always get the wrong description unless the first item in the second group happens to be the same item as the one in the first group. Two things come to mind to remedy that:
Create a new table and split the descriptions up.
Add the table to your report a second time and use one alias for the main group and the second alias for the second group.
CR will give you a message that you already have the table in your report, but you can ignore that. I would give #2 a shot and see how it works. It's definitely less work than creating a brand new table.

Related

How can I sum the same column differently depending on another column type

I have a SQL Query I want to create in Alteryx.  This query goes through an Invoicing table and sums up different charges depending on the location that is associated with it.  So each location can have different types for each column.  Below is an example:
Location FreightCharge InvoiceCharge
A FRT IVC
B FRT, CHG IVC, DTL
Using a query with a case statement worked fine when I only had one location to worry about.  Now I will potentially have hundreds.  I created a Locations table that has the types in it (the table above).  But I'm not convinced it's the right way to do this.
ultimately I would either want a SQL Statement (alteryx) that can do this from the ground up or (more likely) a workflow I can use to loop through locations which links to my reference table and automatically tallies this data.
Any ideas?
However, it would be nice if I could run this for each location, appending it to an invoice table.  
I've tried creating a reference table and joining it to my main invoicing query but I can't get it to filter by the correct data. I've considered creating a Alteryx or SSIS Package that loops through each record, however I don't need to loop through things one record at a time. Just one location at a a time.
This would go into a table like this for location A:
Select Location, InvoiceNumber, Case WHEN InvoiceType IN('FRT') THEN InvoiceAmount Else 0 End as FreightCharge --**I want this to be dynamic depending on location, Case WHEN InvoiceType IN('IVC','DTL') then InvoiceAmount Else 0 End as InvoiceCharge --**I want this to be dynamic depending on location From Invoicing Where InvoiceDate = Today
I would want an invoicing table with all locations and their summed values (how they should sum according to the reference table) all in one table.
Suppose you organize your lookup table as:
Location GroupLabel InvoiceType
A Freight FRT
A Invoice IVC
B Freight FRT
B Freight CHG
B Invoice IVC
B Invoice DTL
And it sounds like your data is something like...
Location InvoiceNumber InvoiceAmount InvoiceType
A 1 1.00 FRT
A 1 2.00 IVC
A 2 3.00 FRT
A 2 4.00 IVC
B 3 5.00 FRT
B 3 6.00 IVC
B 4 7.00 CHG
B 4 8.00 DTL
Then, I think the following would provide what you're after...
Select
i.Location
, i.InvoiceNumber
, l.GroupLabel
, Sum(i.Amount)
From
Invoicing i
Inner Join LookupTable l
on l.Location = i.Location
and l.InvoiceType = i.InvoiceType
Group By
i.Location
, i.InvoiceNumber
, l.GroupLabel
In Alteryx, it should be pretty straightforward to do the Join on both Location and InvoiceType before doing an Aggregation grouped by the three fields shown and summing InvoiceAmount.

Left join in tabular model

I have 2 tables as below.
BILLING
AccountId RatingDate Load
1280582 2018-01-04 15:20:13.000 130.000
421947 2018-01-04 11:44:58.000 176.000
1033717 2018-01-04 10:52:23.000 234.000
RATING
AccountId RatingDate RatingMethod
1280582 2018-01-04 15:20:13.000 A
421947 2018-01-04 11:44:58.000 A
1033717 2018-01-04 10:52:23.000 A
I need to create a measure in Billing table to calculate the sum of Load column. I have the SQL query to perform the same but I am not able to create the measure with the same logic.
SELECT SUM(b.Load)
FROM Billing b
LEFT JOIN Rating r
ON b.AccountId = r.AccountId
AND b.RatingDate = r.RatingDate
WHERE r.RatingMethod = 'A'
Can someone help me with the dax formula for creating the measure?
There are a few ways to approach this including
Do the left join in the query editor.
Create bridge tables or unique indexing columns to relate your two tables.
Write a measure using the LOOKUPVALUE function.
If you're doing a bunch of other stuff, you'll probably want to consider option #1 or #2, but for just this particular measure, I'll show you #3.
LoadSum = CALCULATE(SUM(Billing[Load]),
FILTER(Billing,
LOOKUPVALUE(Rating[RatingMethod],
Rating[AccountID], Billing[AccountID],
Rating[RatingDate], Billing[RatingDate])
= "A"))
The above sums over the [Load] after filtering rows where [RatingMethod] = "A" in the Rating table (and matching on the ID and date columns).
For #1, select your Rating query and click Merge Queries (Home tab).
Select the columns you want to join one (Ctrl+Click in the same order on both of them). Keep the default Left Outer Join and hit OK.
Once they're merged, you'll have a new column named Billing. Click the expand icon in the top right corner of the column and select which columns you want to expand (select Load only).
Once expanded, your table should look like this:
RATING
AccountId RatingDate RatingMethod Load
1280582 2018-01-04 15:20:13 A 130
421947 2018-01-04 11:44:58 A 176
1033717 2018-01-04 10:52:23 A 234

SSRS Matrix Grouping Vertically to keep headers in same column? Is it not possible?

using SSRS 2008 R2 here.
I've been able to get a similar layout to work with a regular tablix, where I get each group header to fall on top of each other in the same column by adding a row within that group, however I need to use a Matrix because of a dynamic column (month below). When I try to add another row, it only adds a row where the monthly data starts, not in the headers. So the headers stay in their each column. In trying to keep the example as easy as possible, I'm trying to do something like this (Store theme).
STORE NAME | MONTHS
STATE | SALES
TOWN(S) | SALES
which woudl look something like this in a Matrix
WALMART JAN FEB MARCH etc....
TEXAS | 3000 2000 6000
HOUSTON | 1000 500 2500
AUSTIN | 2000 1500 3500
I've only been able to produce something like this where each group is a seperate column:
STORE | STATE | CITY | JAN | FEB | MAR |
WALMART | TEXAS | HOUSTON | 1000 | 500 | 2500 |
| AUSTIN | 2000 | 1500 | 3500 |
Again, I've been able to get a regular Tablix formatted like this, but a Matrix I'm struggling with. Can anyone help me on how to do this? Thank you in advance!!
It is possible using a tablix/matrix and adding some special grouping settings.
Add a tablix with the City field in Row Groups pane:
Right click the City group, select Add Group / Parent Group. Choose State and set Add a Group Header
Delete the left most column (State column added in the previous step).
Note the group is still present.
Right click the STATE group and add a Parent Group as step 2. In this case choose STORENAME
Again delete the left most column (Store Name column added in the previous step)
You will get the following tablix.
Delete the first row
Set the Fields using the Row Group hierarchy order. STORENAME/STATE/CITY
Right click the first cell in the next column and add a group / Column Group / Parent Group. Choose MONTH in group by.
Delete the first row.
Set SUM(Fields!Sales.Value) in the next cells in the same column.
After these steps you will get a tablix like this in design window.
It should produce:
Let me know if this helps.

PostgreSQL Fuzzy Searching multiple words with Levenshtein

I am working out a postgreSQL query to allow for fuzzy searching capabilities when searching for a company's name in an app that I am working on. I have found and have been working with Postgres' Levenshtein method (part of the fuzzystrmatch module) and for the most part it is working. However, it only seems to work when the company's name is one word, for example:
With Apple (which is stored in the database as simply apple) I can run the following query and have it work near perfectly (it returns a levenshtein distance of 0):
SELECT * FROM contents
WHERE levenshtein(company_name, 'apple') < 4;
However when I take the same approach with Sony (which is stored in the database as Sony Electronics INC) I am unable to get any useful results (entering Sony gives a levenshtein distance of 16).
I have tried to remedy this problem by breaking the company's name down into individual words and inputting each one individually, resulting in something like this:
user input => 'sony'
SELECT * FROM contents
WHERE levenshtein('Sony', 'sony') < 4
OR levenshtein('Electronics', 'sony') < 4
OR levenshtein('INC', 'sony') < 4;
So my question is this: is there some way that I can accurately implement a multi-word fuzzy search with the current general approach that I have now, or am I looking in the complete wrong place?
Thanks!
Given your data and the following query with wild values for the Levenshtein Insertion (10000), Deletion (100) and Substitution (1) cost:
with sample_data as (select 101 "id", 'Sony Entertainment Inc' as "name"
union
select 102 "id",'Apple Corp' as "name")
select sample_data.id,sample_data.name, components.part,
levenshtein(components.part,'sony',10000,100,1) ld_sony
from sample_data
inner join (select sd.id,
lower(unnest(regexp_split_to_array(sd.name,E'\\s+'))) part
from sample_data sd) components on components.id = sample_data.id
The output is so:
id | name | part | ld_sony
-----+------------------------+---------------+---------
101 | Sony Entertainment Inc | sony | 0
101 | Sony Entertainment Inc | entertainment | 903
101 | Sony Entertainment Inc | inc | 10002
102 | Apple Corp | apple | 104
102 | Apple Corp | corp | 3
(5 rows)
Row 1 - no changes..
Row 2 - 9 deletions and 3 changes
Row 3 - 1 insertion and 2 changes
Row 4 - 1 deletion and 4 changes
Row 5 - 3 changes
I've found that splitting the words out causes a lot of false positives whe you give a threshold. You can order by the Levenshtein distance to position the better matches close to the top. Maybe tweaking the Levenshtein variables will help you to order the matches better. Sadly, Levenshtein doesn't weight earlier changes differently than later changes.

Hierarchical SQL Queries, SSRS 2008, and Summing Columns

I am building an SSRS report and am having a bit of trouble figuring out how to implement it.
First, here is the basic structure of the data:
Level 1a
Level 2a
Level 2b
Level 2c
Level 3a
Level 1b
Level 1c
In the database, each level has an id and a parent id where all parent ids at the root (parents of level 1) are 0. Additionally, each level has a column with a numeric value. For example, I might have:
Level1a
ParentId = 0
Id = 1
DataValue = 42
Level2a
ParentId = 1
Id = 2
DataValue = 1
Currently, I have implemented a common table expression to get the hierarchy structure and levels of the data:
WITH cteTable(id, parentId, data, level) AS
(SELECT id,
parentId,
data,
1 AS level
FROM sampleTable
WHERE (parentId = 0)
UNION ALL
SELECT b.id,
b.parentId,
b.data,
c.level + 1 AS Expr1
FROM sampleTable AS b
INNER JOIN cteTable AS c ON b.parentId= p.id
)
SELECT id,
parentId,
data,
level
FROM cteTable
so the with the sample data from earlier, the results of the query would be:
+----+----------+------+-------+
| id | parentId | data | level |
|----+----------+------+-------+
| 1 | 0 | 42 | 1 |
| 2 | 1 | 1 | 2 |
+----+----------+------+-------+
From here, I need to build a report that will sum up the data to the root level. For example, the report would show that the data sum for id 1 is 43. One thing I don't know for certain is how deep the levels go - there will be some instances where there are no child levels and others where the tree goes a few levels deep.
There are two options I am considering right now. One is to create a drill down report which will show the data at each level with a sum where available. For example:
-Level1a SUM_LEVEL2_AND_LEVEL1a_DATA
Level2a DATA
Level2b DATA
-Level2c SUM_LEVEL3_AND_LEVEL2c_DATA
Level3a DATA
Level1b DATA
Level1c DATA
The other is to sum the data to the root and show a simple table in the report with the parent totals only. For example:
Level1a SUM_LEVEL1A_AND_ALL_CHILDREN_DATA
Level1b SUM_LEVEL1B_AND_ALL_CHILDREN_DATA
Level1c SUM_LEVEL1C_AND_ALL_CHILDREN_DATA
I can't seem to figure out how to get the drill down report working with the googling I've done (there is a link here that seemed to be useful, but I just couldn't get it to work).
Changing the database schema is not an option.
Does anyone know of any good resources I could use to get started or have any ideas on how to proceed with this?
Let me know if I am missing anything...
I finally found a solution to this one.
The common table expression (CTE) was a good start. The only change I made to it was in the recursive definition - instead of collecting the id of the immediate parent for each child, I assigned it the grandparent's id (the parent id the immediate parent had). This meant that every child was assigned the ultimate parent id instead of moving up only one step in the hierarchy. From there, it was pretty straightforward to use this in the report.
I put the CTE in a stored procedure of its own - the only purpose is to bring back the entire hierarchy. From there, I created another stored procedure, which combined the CTE with a different stored procedure. At this time, I applied the filters and returned the final result set.