In the most basic sense I have a fact table and two dimensions but my referenced relationship is only returning the top row for each CaseID.
FactTable
DimCases
DimCasesRepeating
All 3 tables are linked by a field called CaseID.
We have extracted data out of an XML into DimCases in column format. Most of the data in the XML only outputs once but some tags repeat, this can happen multiple times. Any of the data that repeats was extracted so that it goes into DimCasesRepeating and is not in DimCases.
DimCases has a regular relationship between CaseID & CaseID in FactTable.
DimCases is then used as an intermediary table. A referenced relationship is created between DimCases & DimCasesRepeating on CaseID & CaseID.
The CaseID for DimCases returns ok but you only ever get one CaseID returned from DimCaseRepeating for each Case.
Eg. DimCases Table
CaseID, MainDetails
1, England
2 , Scotland
3 , Wales
CaseID is only in DimCases once for each case but that caseID can be in DimCasesRepeating multiple times.
Eg. DimCasesRepeating Table
CaseID, RepeatingDetails
1, a
1, b
2, c
2, d
If you choose 1 from DimCases & then pull across CaseID from DimCasesRepeating you only ever get one record.
OUTPUT
DimCases.CaseID, DimCasesRepeating.CaseID
1, a
REQUIRED OUTPUT
DimCases.CaseID, DimCasesRepeating.CaseID
1, a
, b
Where am I going wrong?
You need to stop using reference dimensions and start using many-to-many dimensions.
Create a DimRepeatingDetails dimension with RepeatingDetails a, b, c, and d. The table should include a RepeatingDetailsID column. Add this as a dimension in the cube.
Create a FactCaseRepeatingDetails table with CaseID and RepeatingDetailsID. Add this has a hidden (meaning the count measure is hidden) measure group in the cube.
Go to the Dimension Usage tab. On the existing measure group for your "FactTable" you mentioned in your question add a relationship to DimRepeatingDetails. But instead of choosing Regular choose type of many-to-many. And make FactCaseRepeatingDetails the intermediate measure group.
Now your report should work correctly.
Related
I would like to update an existing table (table 1) based on two variables. The existing table is a health care dataset that shows patient admit, consult, and discharge dates. I have a separate dataset (table 2) that has more consult dates to add. So, I would like to upload/update the consult date from table 2 into table 1 by matching the patient ID number and admission date.
I have already created a query that merges table 1 and 2 successfully, but I am unable to edit any of the variables manually when I have merged them.
SELECT Inpatient.PatientID, Inpatient.AdmissionDate, Inpatient.Admit, FirstNote.ConsultDate, Inpatient.DischargeDate
FROM Inpatient INNER JOIN
FirstNote
ON (Inpatient.AdmissionDate = FirstNote.Admit) AND
(Inpatient.PatientID = FirstNote.PatientID);
I expect the final table to have the following variables:
Patient ID, AdmissionDate, ConsultDate, DischargeDate
with updated data under ConsultDate from table 2
I have one table of facilities, identified by unique facility IDs. This is linked by facility_id to another table showing the multiple facility outputs, that is is the output table there are multiple records for each facility id, each record specifying a different output. I'd like to select all facilities with various combinations of outputs, ie all facilities with only output 1, or all with outputs 2 & 3.
Thanks
edit:
ok, here we go. I have tblFacilities
facility_id blahblah1 blahblah2 etc...
1
2
3
4
and tblOutputs
facility_id output
1 thermal
1 electricity
2 thermal
3 electricity
I would like to be able to return records from tblFacilities for all facilities that: (1) have both thermal and electricity outputs; (2) have only thermal outputs. The tables are joined on facility_id, and facility_id has unique values in tblFacility.
Thanks!
I've a data of an ERP Standard Feature called Bill of Material, Where It'll have a tree Structure.
I has 4 column as Unique_Id,from,is_main and srno
So here 1st Column is an unique Id,2nd Column indicated its Parent row, 3rd Column Indicates whether it has a sub set or not and 4th is just another series of the Subset.
Link for the Screenshots : Screenshots
So Picture indicates the Hierarchy of the above data.
So I need to get the Answer as Level of Hierarchy. As picture shows the Maximum of 4 stages of Hierarchy.
This is Sample query, You have to change according to you
WITH temp AS
(
SELECT A.Unique_Id, A.from, A.is_main , A.srno
FROM [dbo].[Your_Table_Name] A
UNION ALL
SELECT B.Unique_Id, A.from, B.is_main , B.srno
FROM temp AS B
INNER JOIN [dbo].[Your_Table_Name] A ON B.from= A.Unique_Id
WHERE A.from IS NOT NULL
)
SELECT * FROM temp
I have a table in SQL Server that contains the following columns :
Id Name ParentId LevelOrder
8 vehicle 0 0/8/
9 car 8 0/8/9/
10 bike 8 0/8/10/
11 House 0 0/11/
...
This creates a tree.
Say that I have the LevelOrder 0/8/, this should return only the car and bike rows, but how do I handle this in SQL Server?
I have tried :
Select * FROM MyTable WHERE LevelOrder >= '0/8/'
but that does not work.
The underscore character will guarantee at least one character comes after '0/8/', so you don't get a match on the "vehicle" row.
SELECT *
FROM MyTable
WHERE LevelOrder LIKE '0/8/_%'
This code allows you to select values that start with 0/8/
Select * FROM MyTable WHERE LevelOrder like '0/8/%'
Okay -
While #Joe's answer is the simplest and easiest to implement (and possibly better performing than what I'm about to propose...), there are some issues with update anomalies.
Specifically:
You already have a parentId column. You need to synchronize both this and the levelOrder column, or risk inconsistent data. (I believe this also violates 1NF, although my understanding of the exact definition is a little sketchy...)
levelOrder contains the entire heirarchy. If any one parent is moved, all children rows must have levelOrder modified to reflect this (potentially very messy).
In light of this, here's what I recommend:
Drop the levelOrder column, as its existence will (generally) cause problems.
Use a recursive CTE and the parentId column to build the heirarchy dynamically. Either leave the column where it is, or move it to a dedicated relationship table. Moving one parent then requires only one cell to be updated, and cannot result in any (data, not semantic) anomalies. The CTE should look similar to this form (will need to be adjusted for purpose):
WITH heir_parent (parentId, id) as (SELECT parentId, id
FROM table
WHERE id =
UNION ALL
SELECT b.parentId, b.id
FROM heir_parent as a
JOIN table as b
ON b.parentId = a.id)
At the moment, the CTE returns a list of all children of the given id, with their id and their immediate parent. It can be adjusted to return a number of other things as well - although I recommend that the CTE be used only to generate the relationship, and join externally to get the remaining data.
I have a problem in sql where I need to generate a packing list from a list of transactions.
Data Model
The transactions are stored in a table that contains:
transaction id
item id
item quantity
Each transaction can have multiple items (and coincidentally multiple rows with the same transaction id). Each item then has a quantity from 1 to N.
Business Problem
The business requires that we create a packing list, where each line item in the packing list contains the count of each item in the box.
Each box can only contain 160 items (they all happen to be the same size/weight). Based on the total count of the order we need to split items into different boxes (sometimes splitting even the individual item's collection into two boxes)
So the challenge is to take that data schema and come up with the result set that includes how many of each item belong in each box.
I am currently brute forcing this in some not so pretty ways and wondering if anyone has an elegant/simple solution that I've overlooked.
Example In/Out
We really need to isolate how many of each item end up in each box...for example:
Order 1:
100 of item A100 of item B140 of item C
This should result in three rows in the result set:
Box 1: A (100), B (60) Box 2: B(40), C (120) Box 3: C(20)
Ideally the query would be smart enough to put all of C together, but at this point - we're not too concerned with that.
How about something like
SELECT SUM([Item quantity]) as totalItems
, SUM([Item quantity]) / 160 as totalBoxes
, MOD(SUM([Item Quantity), 160) amountInLastBox
FROM [Transactions]
GROUP BY [Transaction Id]
Let me know what fields in the resultset you're looking for and I could come up with a better one
I was looking for something similar and all I could achieve was expanding the rows to the number of item counts in a transaction, and grouping them into bins. Not very elegant though.. Moreover, because string aggregation is still very cumbersome in SQL Server (Oracle, i miss you!), I have to leave the last part out. I mean putting the counts in one single row..
My solution is as follows:
Example transactions table:
INSERT INTO transactions
(trans_id, item, cnt) VALUES
('1','A','50'),
('2','A','140'),
('3','B','100'),
('4','C','80');
GO
Create a dummy sequence table, which contains numbers from 1 to 1000 (I assume that maximum number allowed for an item in a single transaction is 1000):
CREATE TABLE numseq (n INT NOT NULL IDENTITY) ;
GO
INSERT numseq DEFAULT VALUES ;
WHILE SCOPE_IDENTITY() < 1000 INSERT numseq DEFAULT VALUES ;
GO
Now we can generate a temporary table from transactions table, in which each transaction and item exist "cnt" times in a subquery, and then give numbers to the bins using division, and group by bin number:
SELECT bin_nr, item, count(*) count_in_bin
INTO result
FROM (
SELECT t.item, ((row_number() over (order by t.item, s.n) - 1) / 160) + 1 as bin_nr
FROM transactions t
INNER JOIN numseq s
ON t.cnt >= s.n -- join conditionally to repeat transaction rows "cnt" times
) a
GROUP BY bin_id, item
ORDER BY bin_id, item
GO
Result is:
bin_id item count_in_bin
1 A 160
2 A 30
2 B 100
2 C 30
3 C 50
In Oracle, the last step would be as simple as that:
SELECT bin_id, WM_CONCAT(CONCAT(item,'(',count_in_bin,')')) contents
FROM result
GROUP BY bin_id
This isn't the prettiest answer but I am using a similar method to keep track of stock items through an order process, and it is easy to understand, and may lead to you developing a better method than I have.
I would create a table called "PackedItem" or something similar. The columns would be:
packed_item_id (int) - Primary Key, Identity column
trans_id (int)
item_id (int)
box_number (int)
Each record in this table represents 1 physical unit you will ship.
Lets say someone adds a line to transaction 4 with 20 of item 12, I would add 20 records to the PackedItem table, all with the transaction ID, the Item ID, and a NULL box number. If a line is updated, you need to add or remove records from the PackedItem table so that there is always a 1:1 correlation.
When the time comes to ship, you can simply
SELECT TOP 160 FROM PackedItem WHERE trans_id = 4 AND box_number IS NULL
and set the box_number on those records to the next available box number, until no records remain where the box_number is NULL. This is possible using one fairly complicated UPDATE statement inside a WHILE loop - which I don't have the time to construct fully.
You can now easily get your desired packing list by querying this table as follows:
SELECT box_number, item_id, COUNT(*) AS Qty
FROM PackedItem
WHERE trans_id = 4
GROUP BY box_number, item_id
Advantages - easy to understand, fairly easy to implement.
Pitfalls - if the table gets out of sync with the lines on the Transaction, the final result can be wrong; This table will get many records in it and will be extra work for the server. Will need each ID field to be indexed to keep performance good.