Grouping issue in SSRS - sql

So I have a table that has divisions and sub-divisions. The structure is as follows:
COMPANYID | DIVISIONID | DIVISION | PARENTID
1 | 1 | North | NULL
1 | 2 | South | NULL
1 | 3 | East | NULL
1 | 4 | West | NULL
1 | 5 | Sales | 1
1 | 6 | Service | 1
1 | 7 | Sales | 2
1 | 8 | Service | 2
1 | 9 | Sales | 3
1 | 10 | Service | 3
1 | 11 | Sales | 4
1 | 12 | Service | 4
The idea behind the table is that the data would indicate all of those divisions/subdivisions are the for the same company. Anything with a null PARENTID is a "Division" and anything that has a PARENTID is a "Sub-Division". There will be a max of 2 tiers (Division --> Subdivision). This table would create the following hierarchy:
Company 1
North
Sales
Service
South
Sales
Service
East
Sales
Service
West
Sales
Service
I am trying to make an SSRS report that shows details about the company including a table with all the divisions and sub-divisions. I am using the following query to retrieve a list of all the divisions and subdivisions:
SELECT division, parentid
FROM division
WHERE companyid=#companyid
#companyid is a parameter for the report. My thought process is that I want create a table that has a Parent group and a Detail group where the Parent group would be all those rows that have a null PARENTID and then the Detail group would list all rows whose PARENTID equals the divisionid of Parent row. I'm just not sure how to set that up in the groups. Filters? Separate queries? Do it in the SQL query?
Any and all help is greatly appreciated! Thanks!

For a simple hierarchy with a maximum of 2 levels you can just join the table on itself:
SELECT D1.CompanyId, D1.DivisionId, D1.Division, D2.Division AS Subdivision
FROM DivisionTable D1
INNER JOIN DivisionTable D2 ON D1.DivisionId = D2.ParentId AND D1.CompanyId = D2.CompanyId
WHERE D1.CompanyId = #CompanyId

If i understood your goal correctly, you want the report to display the information in hierarchy mode.
If so you can achieve it with setting a Recursive Hierarchy Group.
Reporting services has the ability to display "hierarchy" information in a "tree" layout
For more information look here
You don't have to create another query the first one that has the CompanyID And the ParentID is just fine

You just need your select statement as a dataset and SSRS can do the grouping for you. You can even tier on multiple levels or better yet collapse and expand your groupings based on filters.
How to get started:
Create your dataset as you have shown
Put in a table object from the toolbox
Only put in the columns of detail data
In the lower left of the 'Design' layout click the 'detail's and click 'add Group>Parent Group'. Select your grouping
If you want you can 'collapse' on demand the details columns. You can choose 'Visibility' on the detail grouping. 'When the report is initially run'>Choose 'Hide'. Check 'Display can be toggled by this report item': Select a cell reference to what you want to expand the details with.

Related

Database Design: Inventory with multilevel packaging

I'm trying to develop a database for my inventory. But I have no idea how to keep track of multilevel packaging.
For example:
I currently have a products and positions table
products
Id | Name
================
1013 | Metal
1014 | Wood
positions
id | Name
================
1 | 1-1-1-1
2 | 1-1-1-2
And my inventory table I was thinking of doing something like this:
Let's say I stored 1 box with 1000 Metal and 1 box with 500 Wood at position 1-1-1-1
ItemId | ProductId | Quantity | PositionId
==========================================
1 | 1013 | 1000 | 1
2 | 1014 | 500 | 1
So I'll label those two boxes with a barcode 1 and 2 respectively, so if I scan them, I can check this table to see the product and quantity inside them.
But I can also put these 2 boxes (1 and 2) inside another box (let's call it box 3), which would generate a new barcode for it that, if scanned, will show both previous boxes and its items. And store this box 3 in another position
And I can also put this box 3 inside a pallet, generating a new code and so on. So basically I can multilevel package N times.
What is the best table structure to keep track of all of this? Thanks in advance for any help!
I would add another column to the products table, make it a BIT and maybe call it BOM, BillOfMaterials, or whatever makes sense to you
So your products Table would look like this
Then you could create another table called BillOfMaterials
Quantity is how many of your products are needed to make up your new product. So for this example 2 metal and 1 wood make a pencil.
I was able to make a good structure:
My products and positions are the same but I created a stock table like:
id | product_id | amount | parent_id | position_id
=====================================================
1 | 1013 | 1000 | 4 | 1
2 | 1013 | 1000 | 4 | 1
3 | 1014 | 500 | 4 | 1
4 | 1234 | NULL | NULL | 1
The 1234 (random id) is a box that contains 2000 metal and 500 wood. I dont save this box in the product table.
When I scan the box with id 3, I perform a recursive cte query:
with recursive bom as (
select *, 1 as level
from testing.stock
where id = '4' #scanned id
union all
select c.*, p.level + 1
from testing.stock c
join bom p on c.parent_id = p.id
)
select product_id as product, sum(amount), position_id
from bom b
left join testing.product pd on b.product_id = pd.id
where pd.id is not null
group by product_id, position_id
which returns:
sum | product | position
2000 | 1013 | 3
500 | 1014 | 3
to get by position I just run a variation of the above query. To perform an update I get the Ids inside that box and run a
update testing.stock set position = '2' where id in (#variation of above query)
I hope this helps someone. This works for N packaging level

SQL Server query - don't want multiple rows with identical data

I have a SQL Server database that has the following three tables - this is simplified for this post.
Stakeholder table (a table that stores a persons personal data... name, address city, state, zip, etc)
Stakeholder_id full_name
---------------------------------------
1 Joe Stakeholder
2 Eric Stakeholder
SH Inquiry table (a table that stores information about when a stakeholder contacts us)
sh_inquiry_id inquiry_link_ID
-----------------------------------------------
1 1
2 1
3 2
Sh Contacts (a table that stores information about when we contact a stakeholder)
sh_contact_id contact_link_id
-----------------------------------------
1 1
2 1
3 2
I want to write a SQL query that shows the stakeholder information once then show all inquiries and all contacts underneath the stakeholder row? is that possible with SQL? So in this case joe stakeholder would be shown once and then there would be 4 rows next (2 inquiries and 2 contacts). Eric stakeholder would be shown once with two rows, 1 inquiry and one contact.
Thanks for any assistance in advance.
As has already been mentioned, you probably want to handle this in your application code. However, you can use a UNION query to sort of do what you want.
With the query below, I changed your latter 2 tables to SH_Inquiry and SH_Contacts (replaced spaces with underscores), which is generally a good habit (it's a bad idea to have spaces in your object names). Also, depending on how your tables are laid out, you might want to merge your Contacts and Inquiry tables (e.g. have one table, with a contact_type field that identifies it as "inbound" or "outbound").
Anyways, using a CTE and union:
WITH Unionized AS
(
SELECT
stakeholder_id,
full_name,
NULL AS contact_or_inquiry,
NULL AS contact_or_inquiry_id
FROM Stakeholder
UNION ALL
SELECT
inquiry_link_id AS stakeholder_id,
NULL AS full_name,
'inquiry' AS contact_or_inquiry,
sh_inquiry_id AS contact_or_inquiry_id
FROM SH_Inquiry
UNION ALL
SELECT
contact_link_id AS stakeholder_id,
NULL AS full_name,
'contact' AS contact,
sh_contact_id AS contact_or_inquiry_id
FROM SH_Contacts
)
SELECT
full_name,
contact_or_inquiry,
contact_or_inquiry_id
FROM Unionized
ORDER BY
stakeholder_id,
contact_or_inquiry,
contact_or_inquiry_id
giving you these results:
+------------------+--------------------+-----------------------+
| full_name | contact_or_inquiry | contact_or_inquiry_id |
+------------------+--------------------+-----------------------+
| Joe Stakeholder | NULL | NULL |
| NULL | contact | 1 |
| NULL | contact | 2 |
| NULL | inquiry | 2 |
| Eric Stakeholder | NULL | NULL |
| NULL | contact | 3 |
| NULL | inquiry | 1 |
| NULL | inquiry | 3 |
+------------------+--------------------+-----------------------+

Trying to find non-duplicate entries in mostly identical tables(access)

I have 2 different databases. They track different things about inventory. in essence they share 3 common fields. Location, item number and quantity. I've extracted these into 2 tables, with only those fields. Every time I find an answer, it doesn't get all the test cases, just some of the fields.
Items can be in multiple locations, and as a turn each location can have multiple items. The primary key would be location and item number.
I need to flag when an entry doesn't match all three fields.
I've only been able to find queries that match an ID or so, or who's queries are beyond my comprehension. in the below, I'd need a query that would show that rows 1,2, and 5 had issues. I'd run it on each table and have to verify it with a physical inventory.
Please refrain from commenting on it being silly having information in 2 different databases, All I get in response it to deal with it =P
Table A
Location ItemNum | QTY
-------------------------
1a1a | as1001 | 5
1a1b | as1003 | 10
1a1b | as1004 | 2
1a1c | as1005 | 15
1a1d | as1005 | 15
Table B
Location ItemNum | QTY
-------------------------
1a1a | as1001 | 10
1a1d | as1003 | 10
1a1b | as1004 | 2
1a1c | as1005 | 15
1a1e | as1005 | 15
This article seemed to do what I wanted but I couldn't get it to work.
To find entries in Table A that don't have an exactly matching entry in Table B:
select A.*
from A
left join B on A.location = B.location and A.ItemNum = B.ItemNum and A.qty = B.qty
where B.location Is Null
Just swap all the A's and B's to get the list of entries in B with no matching entry in A.

Microsoft SQL report builder: Multiple row 'duplicates' to one row per ID

Microsoft SQL Server report Builder
I have a query which returns a variety of information from our Community Intelligence database which runs something like this:
SELECT
viewadhocorganisation.[org_id]
..../other fields
viewadhocorganisationmainactivities.[Main Activity]
FROM
viewadhocorganisation LEFT JOIN viewadhocorganisationmainactivities
ON viewadhocorganisation.[OrganisationID] = viewadhocorganisationmainactivities.[Organisation ID]
WHERE
viewadhocorganisation.[city name] = 'MyCity'
This returns each organisation with its respective fields on a new row with each of its main activities listed seperately in a new row (i.e duplicating)
hence SELECT DISTINCT does nothing in this instance as each row is not strictly a duplicate
ie return is :
ID | Org Name | other fields | Main Activity
1 | Org 1 | other fields | Activity 1
1 | Org 1 | other fields | Activity 2
1 | Org 1 | other fields | Activity 3
1 | Org 1 | other fields | Activity 4
2 | Org 2 | other fields | Activity 1
2 | Org 2 | other fields | Activity 5
2 | Org 2 | other fields | Activity 7
2 | Org 2 | other fields | Activity 8
Main Activity is a text string populated from a seperate Lookup Table (maintained by a central sysadmin) I have tried various SUM, AGGREGATE, (also tried various JOIN, LOOKUP SET but I seem to be running into a lot of errors though I may be using it incorrectly) but have yet to find a solution to get the desired output where all main activities are in one row seperated by a comma :
Output required:
Org_ID | Org Name | other fields | Main Activity
1 | Org 1 | other fields | Activity 1, Activity 2, Activity 3
2 | Org 2 | other fields | Activity 1, Activity 5, Activity 7
The intention is to get a dump of information to integrated into google maps API showing address of Org 1, org 2 etc showing their main activities which I have a procedure for already but am unable to collate the Main activity field into one row
Edit: I have no access to the back end and can only report from the views and tables created by our vendor
you can use temporary tables to achieve this.
make your desired string of activities in one temporary from viewadhocorganisationmainactivities then join that temp table with your main table i.e viewadhocorganisation.
You need to join the table with itself and use the stuff clause to get the strings in a comma separated format. See this fiddle

Advance Query with Join

I'm trying to convert a product table that contains all the detail of the product into separate tables in SQL. I've got everything done except for duplicated descriptor details.
The problem I am having all the products have size/color/style/other that many other products contain. I want to only have one size or color descriptor for all the items and reuse the "ID" for all the product which I believe is a Parent key to the Product ID which is a ...Foreign Key. The only problem is that every descriptor would have multiple Foreign Keys assigned to it. So I was thinking on the fly just have it skip figuring out a Foreign Parent key for each descriptor and just check to see if that descriptor exist and if it does use its Key for the descriptor.
Data Table
PI Colo Sz OTHER
1 | Blue | 5 | Vintage
2 | Blue | 6 | Vintage
3 | Blac | 5 | Simple
4 | Blac | 6 | Simple
===================================
Its destination table is this
===================================
DI Description
1 | Blue
2 | Blac
3 | 5
4 | 6
6 | Vintage
7 | Simple
=============================
Select Data.Table
Unique.Data.Table.Colo
Unique.Data.Table.Sz
Unique.Data.Table.Other
=======================================
Then the dual part of the questions after we create all the descriptors how to do a new query and assign the product ID to the descriptors.
PI| DI
1 | 1
1 | 3
1 | 4
2 | 1
2 | 3
2 | 4
By figuring out how to do this I should be able to duplicate this pattern for all 300 + columns in the product. Some of these fields are 60+ characters large so its going to save a ton of space.
Do I use a Array?
Okay, if I understand you correctly, you want all unique attributes converted from columns into rows in a single table (detailstable) that has an id and a description field:
Assuming the schema:
datatable
------------------
PI [PK]
Colo
Sz
OTHER
detailstable
------------------
DI [PK]
Description
You can first get all of the unique attributes into its own table with:
INSERT INTO detailstable (Description)
SELECT
a.description
FROM
(
SELECT DISTINCT Colo AS description
FROM datatable
UNION
SELECT DISTINCT Sz AS description
FROM datatable
UNION
SELECT DISTINCT OTHER AS description
FROM datatable
) a
Then to link up the datatable to the detailstable, I'm assuming you have a cross-reference table defined like:
datadetails
------------------
PI [PK]
DI [PK]
You can then do:
INSERT INTO datadetails (PI, DI)
SELECT
a.PI
b.DI
FROM
datatable a
INNER JOIN
detailstable b ON b.Description IN (a.Colo, a.Sz, a.OTHER)
I reckon you want to split description table for different categories, like - colorDescription, sizeDescription etc.
If that is not practical then I would recommend having an extra column showing an category attribute:
DI Description Category
1 | Blue | Color
2 | Blac | Color
3 | 5 | Size
4 | 6 | Size
6 | Vintage | Other
7 | Simple | Other
And then have primary key in this table as combination of ID and Category column.
This will have less chances for injecting any data errors. It will be also easy to track that down.