I have a Datatable That Looks like the Following
╔═══════════════╦═══════════════╦═══════════════╗
║ Product Name ║ Product Price ║ Product Group ║
╠═══════════════╬═══════════════╬═══════════════╣
║ Skirt Red ║ 99 ║ ║
║ Jeans Blue ║ 49 ║ ║
║ Jeans Black ║ 49 ║ ║
║ Skirt Blue ║ 99 ║ ║
║ T-shirt White ║ 20 ║ ║
║ T-shirt Green ║ 20 ║ ║
║ Jeans Grey ║ 49 ║ ║
╚═══════════════╩═══════════════╩═══════════════╝
This is just an example Datatable and the Real Datatable has much more complex names and colors, as you can see there are simular products with different colors now using LINQ i want to make the Datatable Look like th following
╔═══════════════╦═══════════════╦═══════════════╗
║ Product Name ║ Product Price ║ Product Group ║
╠═══════════════╬═══════════════╬═══════════════╣
║ Skirt Red ║ 99 ║ 1 ║
║ Jeans Blue ║ 49 ║ 2 ║
║ Jeans Black ║ 49 ║ 2 ║
║ Skirt Blue ║ 99 ║ 1 ║
║ T-shirt White ║ 20 ║ 3 ║
║ T-shirt Green ║ 20 ║ 3 ║
║ Jeans Grey ║ 49 ║ 2 ║
╚═══════════════╩═══════════════╩═══════════════╝
what defines a group? the price is the same and the name has nothing to do it.
i am new to LINQ and i wonder what would be the best approach to do this and the Datatable i am working with has about 112000 records
so bascily, i need to add products with same price to a group and Add a number beside each products the points to the group
Just group the rows by price and loop through the groups setting the group field of each row in the group to a group number.
Dim query =
From row in table.AsEnumerable
Group row By Price = row.Field(Of Integer)("Product Price") Into ProductGroups = Group
Dim grpNumber = 1
For Each grp In query
For Each row In grp.ProductGroups
row.SetField("Product Group", grpNumber)
Next
grpNumber += 1
Next
Related
I have a table of order information in the following format:
╔══════════════╦══════╦════════════════╦═══════════╦═════════╦══════════╗
║ Order Number ║ Line ║ Item ║ Warehouse ║ Carrier ║ Quantity ║
╠══════════════╬══════╬════════════════╬═══════════╬═════════╬══════════╣
║ 255 ║ 1 ║ STUFFED-ANIMAL ║ WH1 ║ UPS ║ 3 ║
║ 256 ║ 1 ║ BLOCKS ║ WH2 ║ FEDEX ║ 1 ║
║ 257 ║ 1 ║ DOLL ║ WH1 ║ UPS ║ 1 ║
║ 257 ║ 2 ║ DRESS ║ WH1 ║ UPS ║ 3 ║
║ 257 ║ 3 ║ SHOES ║ WH2 ║ UPS ║ 1 ║
║ 258 ║ 1 ║ CHAIR ║ WH3 ║ FEDEX ║ 1 ║
║ 258 ║ 2 ║ CHAIR ║ WH3 ║ UPS ║ 2 ║
╚══════════════╩══════╩════════════════╩═══════════╩═════════╩══════════╝
I am trying to query it in such a way that I partition it into groups based on a unique combination of columns.
In my example, I would like the following result:
╔════════════════╦══════╦════════════════╦═══════════╦═════════╦══════════╗
║ Package-Number ║ Line ║ Item ║ Warehouse ║ Carrier ║ Quantity ║
╠════════════════╬══════╬════════════════╬═══════════╬═════════╬══════════╣
║ 255 ║ 1 ║ STUFFED-ANIMAL ║ WH1 ║ UPS ║ 3 ║
║ 256 ║ 1 ║ BLOCKS ║ WH2 ║ FEDEX ║ 1 ║
║ 257-1 ║ 1 ║ DOLL ║ WH1 ║ UPS ║ 1 ║
║ 257-1 ║ 2 ║ DRESS ║ WH1 ║ UPS ║ 3 ║
║ 257-2 ║ 3 ║ SHOES ║ WH2 ║ UPS ║ 1 ║
║ 258-1 ║ 1 ║ CHAIR ║ WH3 ║ FEDEX ║ 1 ║
║ 258-2 ║ 2 ║ CHAIR ║ WH3 ║ UPS ║ 2 ║
╚════════════════╩══════╩════════════════╩═══════════╩═════════╩══════════╝
To break it down I would like to do the following:
If the order number, warehouse, and carrier are the same that is one 'partition.' If there is only one partition then we just leave the order number as the package number, otherwise we break it down into packages. These packages are numbered by the same set of values being the same, but now have a number denoting which package it is.
I was looking into using row_number() over (partition by... that I found after searching for similar issues but I don't think it is exactly what I'm looking for.
Could someone point me in the right direction?
This is tricky. Having count(distinct) as a window function would help. But there is a convenient trick using the sums of dense_rank()s.
So, I think this does what you want:
select (case when seqnum_asc + seqnum_desc - 1 > 1 -- more than 1 distinct value
then concat(ordernumber, '-', seqnum_asc)
else concat(ordernumber, '') -- just to convert the value to a string
end) as packagenumber,
t.*
FROM (select t.*,
dense_rank() over (partition by ordernumber order by warehouse, carrier) as seqnum_asc,
dense_rank() over (partition by ordernumber order by warehouse desc, carrier desc) as seqnum_desc
from mytable t
) t;
Here is a db<>fiddle.
Note: This does not take into account the ordering by the line number -- because your question doesn't mention that at all. If you only want adjacent rows with the same value to be included in each group, then ask a new question with appropriate sample data and desired results.
Here is an option using Dense_Rank() instead of Row_Number()
Example
Select [Package-Number] = concat([Order Number]
,left(nullif(count(*) over (partition by [Order Number] ),1),0)
+dense_rank() over (partition by [Order Number],warehouse,carrier order by Line)*-1 )
,Line
,Item
,Warehouse
,Carrier
,Quantity
From YourTable
Returns
I have a fact table (document granularity) with 3 amount measures and other qtys measures, those 3 amount measures are not in same currency but related to a type of a visualization.
Reports can have three types of visualization, Document view, Company view, Company Group view.
If you see through document view you should view all kinds of currencies, depending of the document (GBP, EUR, CAN, USA, AUD, etc).
If you see through company view you should see this regarding the currency associated to the company (i.e. Company 1 is EUR, Company 2 is USD, etc).
Company Group is always EUR.
Example:
fact table
╔═══════════════════════════════════════════════════════════════════════════╗
║ Fact Document ║
╠════════════╦═════════════╦══════════════╦═════════════╦═══════════════════╣
║ Company ID ║ Doc ID ║ Mtr Document ║ Mtr Company ║ Mtr Company Group ║
╠════════════╬═════════════╬══════════════╬═════════════╬═══════════════════╣
║ 1 ║ 101 ║ 100 ║ 90 ║ 95 ║
╠════════════╬═════════════╬══════════════╬═════════════╬═══════════════════╣
║ 2 ║ 102 ║ 250 ║ 150 ║ 120 ║
╠════════════╬═════════════╬══════════════╬═════════════╬═══════════════════╣
║ 3 ║ 103 ║ 400 ║ 200 ║ 170 ║
╚════════════╩═════════════╩══════════════╩═════════════╩═══════════════════╝
dim document
╔════════════════════════════════════════════════════════════════════════╗
║ Dim Document ║
╠════════╦═══════════════════╦══════════════════╦════════════════════════╣
║ Doc ID ║ Document Currency ║ Company Currency ║ Company Group Currency ║
╠════════╬═══════════════════╬══════════════════╬════════════════════════╣
║ 101 ║ USD ║ GBP ║ EUR ║
╠════════╬═══════════════════╬══════════════════╬════════════════════════╣
║ 102 ║ CAN ║ USD ║ EUR ║
╠════════╬═══════════════════╬══════════════════╬════════════════════════╣
║ 103 ║ AUD ║ USD ║ EUR ║
╚════════╩═══════════════════╩══════════════════╩════════════════════════╝
dim visualization type (Manual and Static dimension with no change)
╔═══════════════════════╦═════════════════════════╗
║ Visualization type ID ║ Visualization type Name ║
╠═══════════════════════╬═════════════════════════╣
║ 1 ║ Document view ║
║ 2 ║ Company view ║
║ 3 ║ Company Group view ║
╚═══════════════════════╩═════════════════════════╝
dim currency
╔══════════╗
║ Currency ║
╠══════════╣
║ EUR ║
║ USD ║
║ GBP ║
║ CAN ║
╚══════════╝
I want to choose visualization type and dynamically select the correct measure (what you have done).
But I also want to select dynamically the currency associated to that measure.
So I want to link one dimension to the other so I can have only a currency attribute and I don't want to have 3 different currency attributes.
Desirable output:
Document view selected
╔═════════╦════════╦══════════╗
║ Doc Id ║ Amount ║ Currency ║
╠═════════╬════════╬══════════╣
║ 101 ║ 100 ║ USD ║
║ 102 ║ 250 ║ CAN ║
║ 103 ║ 450 ║ AUD ║
╚═════════╩════════╩══════════╝
Company view selected
╔═════════╦════════╦══════════╗
║ Doc Id ║ Amount ║ Currency ║
╠═════════╬════════╬══════════╣
║ 101 ║ 90 ║ GPB ║
║ 102 ║ 150 ║ USD ║
║ 103 ║ 200 ║ USD ║
╚═════════╩════════╩══════════╝
Company Group view selected
╔═════════╦════════╦══════════╗
║ Doc Id ║ Amount ║ Currency ║
╠═════════╬════════╬══════════╣
║ 101 ║ 95 ║ EUR ║
║ 102 ║ 120 ║ EUR ║
║ 103 ║ 170 ║ EUR ║
╚═════════╩════════╩══════════╝
Is it possible to do this?
All the best and thank you!
Ricardo Castro
UPDATE
I did this below and I am getting the values 1, 2 or 3 as I select the type in "dim visualization type"
CREATE MEMBER [Coin]
AS CASE WHEN [visualization type].[visualization type].CurrentMember.MEMBERVALUE = 'Document view'
THEN 1
ELSE (CASE WHEN [visualization type].[visualization type].CurrentMember.MEMBERVALUE = 'Company view'
THEN 2
ELSE 3 END) END,
VISIBLE = 1 ;
I need to get the attribute values. I have tried:
[Document].[Document Currency].firstchild
STRTOMEMBER("[Document].[Document Currency].MEMBERS")
STRTOMEMBER('[Document].[Document Currency].[Document Currency].FirstChild', CONSTRAINED)
If I put the follow code I get the "all" that is the only one I don't want :P :
[Document].[Document Currency].CurrentMember.Properties("Name")
Any thoughts?
You can create a standard set of calculated metrics based on the required conversions and use SCOPE statements based on the dimension to swizzle the definition of the metrics to different calculations based on the view selected.
https://learn.microsoft.com/en-us/analysis-services/multidimensional-models/mdx/managing-scope-and-context-mdx
I need to return a list of customer names from a purchase summary table but only if the customer has bought 2 definitive items within the 1 transaction.
For example table 'transaction'
╔══════════════╦════════╦══════════════╦════════╗
║ CustomerName ║ Item ║ Transaction# ║ Amount ║
╠══════════════╬════════╬══════════════╬════════╣
║ Smith ║ Hammer ║ 1 ║ 50.00 ║
║ Smith ║ Nail ║ 1 ║ 4.00 ║
║ Smith ║ Screw ║ 1 ║ 5.00 ║
║ Brown ║ Nail ║ 2 ║ 4.00 ║
║ Brown ║ Screw ║ 2 ║ 4.00 ║
║ Jones ║ Hammer ║ 3 ║ 50.00 ║
║ Jones ║ Screw ║ 3 ║ 4.00 ║
║ Smith ║ Nail ║ 4 ║ 50.00 ║
║ Smith ║ Hammer ║ 4 ║ 4.00 ║
║ Smith ║ Screw ║ 5 ║ 5.00 ║
╚══════════════╩════════╩══════════════╩════════╝
I only want to return customers who have bought a Hammer and a screw in the same transaction. It doesn't matter what other items were bought in the same transaction, I only need the details for the hammer and the screw, and only if both the hammer and screw were present in the same transaction.
So the above only needs to return:
╔══════════════╦════════╦══════════════╦════════╗
║ CustomerName ║ Item ║ Transaction# ║ Amount ║
╠══════════════╬════════╬══════════════╬════════╣
║ Smith ║ Hammer ║ 1 ║ 50.00 ║
║ Smith ║ Screw ║ 1 ║ 5.00 ║
╚══════════════╩════════╩══════════════╩════════╝
Because only transaction 1 contained both a hammer and a screw in the same transaction.
Use a sub-select to find transactions including both Hammer and Screw:
select CustomerName, Item, Transaction#, Amount
from purchase
where Transaction# in (select Transaction# from purchase
where Item in ('Hammer', 'Screw')
group by Transaction#
having count(distinct Item) = 2)
and Item in ('Hammer', 'Screw')
Remove last row if also Nail row should be returned!
Related to this SQL question - Group consecutive rows of same value using time spans
I want to convert this table:
╔═══════════╦════════════╦═══════════╦═══════════╦═════════╗
║ Classroom ║ CourseName ║ Lesson ║ StartTime ║ EndTime ║
╠═══════════╬════════════╬═══════════╬═══════════╬═════════╣
║ 1001 ║ Course 1 ║ Lesson 1 ║ 0800 ║ 0900 ║
║ 1001 ║ Course 1 ║ Lesson 2 ║ 0900 ║ 1000 ║
║ 1001 ║ Course 1 ║ Lesson 3 ║ 1000 ║ 1100 ║
║ 1001 ║ Course 2 ║ Lesson 10 ║ 1100 ║ 1200 ║
║ 1001 ║ Course 2 ║ Lesson 11 ║ 1200 ║ 1300 ║
║ 1001 ║ Course 1 ║ Lesson 4 ║ 1300 ║ 1400 ║
║ 1001 ║ Course 1 ║ Lesson 5 ║ 1400 ║ 1500 ║
╚═══════════╩════════════╩═══════════╩═══════════╩═════════╝
To this table:
╔═══════════╦════════════╦═══════════╦═════════╗
║ Classroom ║ CourseName ║ StartTime ║ EndTime ║
╠═══════════╬════════════╬═══════════╬═════════╣
║ 1001 ║ Course 1 ║ 0800 ║ 1100 ║
║ 1001 ║ Course 2 ║ 1100 ║ 1300 ║
║ 1001 ║ Course 1 ║ 1300 ║ 1500 ║
╚═══════════╩════════════╩═══════════╩═════════╝
The SQL solution from the related question works but the query takes forever because I have a lot of data in my tables and the SQL Query is using 2 sub queries.
Actually the original table is a query with 3 joins in itself so the complexity is even bigger.
I am looking for an SSRS solution.
Is it possible using some "VB Magic" or other kind of magic in SSRS 2008 R2 to do this ?
I have a table like below which would have the product description
╔════╦══════════════╦══════╗
║ Id ║ name ║ price║
╠════╬══════════════╬══════╣
║ 1 ║ Apple ║ 23 ║
║ 2 ║ shirt ║ 148 ║
║ 3 ║ computer ║ 101 ║
║ 4 ║ printer ║ 959 ║
╚════╩══════════════╩══════╝
and another table which is holding the attributes like linked by the ID
╔════╦══════════════╦══════╗
║ Id ║ attr_name ║ Value║
╠════╬══════════════╬══════╣
║ 1 ║ color ║ red ║
║ 1 ║ size ║ xl ║
║ 1 ║ brand ║ App ║
║ 2 ║ color ║ blue║
║ 2 ║ size ║ l ║
║ 3 ║ color ║ blue║
║ 3 ║ size ║ xxl ║
║ 3 ║ brand ║ HP ║
╚════╩══════════════╩══════╝
Is there any possible way to bring a table like below if I know the attribute name is going to be only color size and brand
╔════╦══════════╦═══════╦═══════╦══════╦══╗
║ id ║ name ║ color ║ brand ║ size ║ ║
╠════╬══════════╬═══════╬═══════╬══════╬══╣
║ 1 ║ apple ║ red ║ app ║ xl ║ ║
║ 2 ║ shirt ║ blue ║ ║ l ║ ║
║ 3 ║ computer ║ blue ║ HP ║ XXL ║ ║
║ 4 ║ printer ║ ║ ║ ║ ║
╚════╩══════════╩═══════╩═══════╩══════╩══╝
You should be able to use an aggregate function with a CASE expression to convert the rows into columns:
select d.id,
d.name,
max(case when a.attr_name = 'color' then a.value end) color,
max(case when a.attr_name = 'brand' then a.value end) brand,
max(case when a.attr_name = 'size' then a.value end) size
from product_description d
inner join product_attributes a
on d.id = a.id
group by d.id, d.name;
See SQL Fiddle with Demo.
Since you are using Oracle 11g, then you can use the PIVOT function to get the result:
select id, name, Color, Brand, "Size"
from
(
select d.id, d.name,
a.attr_name, a.value
from product_description d
inner join product_attributes a
on d.id = a.id
) src
pivot
(
max(value)
for attr_name in ('color' as Color,
'brand' as Brand,
'size' as "Size")
) p;
See SQL Fiddle with Demo