Parsing an column containing integers - sql

I am writing a query that pulls 50 fields from 12 sub-queries in the FROM statement. Each sub query is left-joined on two fields the Item SKU and Brand ID. However there is one table where the Brand ID is concatenated in a comma delimited column.
My problem is that I am having trouble parsing this column so that I can use it as a foreign key to join to the other sub-queries. I tried setting the column = to a variable and then using the String_Split function, but was getting the error 'No column selected for column 1' in the query. If anyone has any suggestions of how to parse this data into a NEW row so that SKU that has multiple brands associated to it each has a row showing that SKU and Brand. I have added a screen shot of the data that needs to be parsed. Thanks!

Isn't this example on the MSSQL docs exactly what you're trying to do?
+-----------+--------------------+----------------------------+
| ProductId | Name | Tags |
+-----------+--------------------+----------------------------+
| 1 | Full-Finger Gloves | clothing,road,touring,bike |
| 2 | LL Headset | bike |
| 3 | HL Mountain Frame | bike,mountain |
+-----------+--------------------+----------------------------+
gets transformed into (note the change in the column name!)
+-----------+--------------------+----------+
| ProductId | Name | value |
+-----------+--------------------+----------+
| 1 | Full-Finger Gloves | clothing |
| 1 | Full-Finger Gloves | road |
| 1 | Full-Finger Gloves | touring |
| 1 | Full-Finger Gloves | bike |
| 2 | LL Headset | bike |
| 3 | HL Mountain Frame | bike |
| 3 | HL Mountain Frame | mountain |
+-----------+--------------------+----------+
using
SELECT ProductId, Name, value
FROM Product
CROSS APPLY STRING_SPLIT(Tags, ',');
Since you didn't share any code, it's impossible for me to be more specific... but this example really seems to me should be the piece you're missing.

Related

How to design tables to allow for multi-field query on one row

I am very new to database design and am using MS Access to try achieve my task. I am trying to create a database design that will allow for the name and description of two items to be queried
on a single row of information. Here is the problem: certain items are converted to other particular items -
any item can have multiple conversions performed on it, and all conversions will have two (many) items involved.
In this sense, we have a many-to-many relationship which necessitates the use of an intermediate table. My
tables must be structured in a way that allows for me to, in one row, query the Item ID's and names
of which items were involved in conversions.
My current table layout is as follows:
Items
+--------+----------+------------------+--+
| ItemID*| ItemName | ItemDescription | |
+--------+----------+------------------+--+
| 1 | DESK | WOOD, 4 LEG | |
| 2 | SHELF | WOOD, SOLID BASE | |
| 3 | TABLE | WOOD, 4 LEG | |
+--------+----------+------------------+--+
ItemConversions
+------------------+--------------+
| ConversionID(CK) | Item1_ID(CK) |
+------------------+--------------+
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
+------------------+--------------+
Conversions
+---------------+----------+----------+
| ConversionID* | Item1_ID | Item2_ID |
+---------------+----------+----------+
| 1 | 2 | 1 |
| 2 | 2 | 3 |
| 3 | 1 | 3 |
+---------------+----------+----------+
What I want is for it to be possible to achieve the kind of query I described above, though I don't think
my current layout is going to work for this, since the tables are only being joined on Item1_ID. Any advice
would be appreciated, hopefully my tables are not too specific and this is easily understandable.
A sample query output might look like this:
+--------------+----------+----------+----------+----------+
| ConversionID | Item1_ID | ItemName | Item2_ID | ItemName |
+--------------+----------+----------+----------+----------+
| 1 | 2 | SHELF | 1 | DESK |
+--------------+----------+----------+----------+----------+
I got it working how I wanted to with the help of June7's suggestion - I didn't know you could add in tables
multiple times in the query design page (very useful!). As for the tables, I edited the layout so that I have only
Items and Conversions (I deleted ItemConversions). Using the AS sql command I was able to write a query that pulls
the data I want from the tables. The table and query layout can be seen below:
Items
+--------+----------+------------------+--+
| ItemID*| ItemName | ItemDescription | |
+--------+----------+------------------+--+
| 1 | DESK | WOOD, 4 LEG | |
| 2 | SHELF | WOOD, SOLID BASE | |
| 3 | TABLE | WOOD, 4 LEG | |
+--------+----------+------------------+--+
Conversions
+---------------+----------+----------+
| ConversionID* | Item1_ID | Item2_ID |
+---------------+----------+----------+
| 1 | 2 | 1 |
| 2 | 2 | 3 |
| 3 | 3 | 1 |
+---------------+----------+----------+
Query:
SELECT
Conversions.ConversionID,
Conversions.Item1_ID,
Conversions.Item2_ID,
Items.ItemName,
Items_1.ItemName,
FROM
(
Conversions
INNER JOIN
Items
ON Conversions.Item1_ID = Items.ItemID
)
INNER JOIN
Items AS Items_1
ON Conversions.Item2_ID = Items_1.ItemID;

Want to update table in MS Access to add column and populate based on other column

I have a table (Fruit) in access that is in the form
Fruit, Cost
and I want to update the table so that I will have
Fruit, Cost, Cost bracket
and the cost bracket will be based on cost e.g Cost = .89 - Cost bracket='<1dollar', Cost=2 -Cost bracket ='1-5dollars' etc.
So far I have:
Alter Table [Fruit]
Add [Cost Bracket] Varchar(50)
Update [Cost Bracket]
Set [Cost Bracket] = Switch(Cost<1,'<1 dollar',Cost Between 1 and
5,'1- 5 dollars' etc...)
Rather than modifying the structure of your current table to include a cost bracket description* and then populating this additional field with fixed values dependent upon the value held by the Cost field, an alternative might be to construct a separate table containing the upper & lower bounds of the cost brackets and the corresponding descriptions.
For example, assuming that your Fruit table looks something along the lines of:
+----+-----------+-------+
| ID | fruit | cost |
+----+-----------+-------+
| 1 | Apple | £0.50 |
| 2 | Orange | £0.80 |
| 3 | Pineapple | £3.00 |
| 4 | Grape | £1.50 |
+----+-----------+-------+
You might create a Cost Brackets table with the following structure:
And populate it with the following cost bracket data:
+----+--------+--------+-------------+
| ID | lbound | ubound | description |
+----+--------+--------+-------------+
| 1 | £0.00 | £1.00 | < £1 |
| 2 | £1.01 | £2.00 | < £2 |
| 3 | £2.01 | £5.00 | < £5 |
+----+--------+--------+-------------+
Then, you can link the two using a query such as:
select f.*, c.description
from fruit f left join cost_brackets c on (f.cost between c.lbound and c.ubound)
Yielding the following result for the above sample data:
+----+-----------+-------+-------------+
| ID | fruit | cost | description |
+----+-----------+-------+-------------+
| 1 | Apple | £0.50 | < £1 |
| 2 | Orange | £0.80 | < £1 |
| 3 | Pineapple | £3.00 | < £5 |
| 4 | Grape | £1.50 | < £2 |
+----+-----------+-------+-------------+
This approach has the distinct advantage that, if you subsequently decide to change the ranges of your cost brackets and their associated descriptions, the change need only be made in one place and the values will cascade through all queries which reference the Cost Brackets table.
Whereas, with your current approach, any change to the cost brackets would involve:
Changing the hard-coded cost brackets found within the Switch functions used in every query (and hope that you've covered them all).
Update the values held by every table which contains the cost bracket description and hope that the value shown by a table has been suitably updated and reflects the current cost brackets.
*Which seems like it should be a one-time task and part of your database design, rather than an operation to be performed by code (unless perhaps you are generating the table on-the-fly?)

Concatenating multiple entries for a given group on large data set in Access

I have a question regarding joining some large tables then attempting to concatenate multiple entries of an attribute. The data is stored in Access which is where I am attempting to restructure the data via queries for my use case.
I am able to join the tables fine as seen in example.. but not sure what is the best method for concatenating multi-valued attributes.. my data set is huge so I have been having performance issues.
I have created some comparable data I am working with to give an idea on how I am joining data. I have noted the number of rows that I have for each table.
TabOrders (121,965 rows)
------------------------------------------
OrderNum | Product | ConfigInstance
------------------------------------------
1 | Product1| 100
2 | Product2| 200
TabConfigurations (121,965 rows)
-------------------------------------
ConfigInstance | Configuration
-------------------------------------
100 | C100
200 | C200
TabConfigDetails (4,021,244 rows)
--------------------------------------
Configuration | ConfigIndicator
--------------------------------------
C100 | A1V2
C100 | A2V1
C100 | A3V1
C100 | A3V2
C100 | A4V2
C200 | A1V1
C200 | A2V2
C200 | A2V4
C200 | A3V4
C200 | A3V5
C200 | A4V2
TabAttributes (27,665 rows)
-------------------------------------------
ConfigIndicator | Attribute | Value
-------------------------------------------
A1V1 | Product | Car
A1V2 | Product | Bike
A1V3 | Product | Motorcycle
A1V4 | Product | Go Cart
A2V1 | Color | Red
A2V2 | Color | Green
A2V3 | Color | Blue
A2V4 | Color | Orange
A3V1 | Accessories| Helmet
A3V2 | Accessories| Cup Holder
A3V3 | Accessories| Cargo
A3V4 | Accessories| Trailer
A3V5 | Accessories| GPS
A4V1 | Size | Small
A4V2 | Size | Large
Here is the query Ive used to join everything:
SELECT TabOrders.OrderNum, TabOrders.Product, TabAttributes.Attribute, TabAttributes.Value
FROM ((TabOrders INNER JOIN TabConfigurations ON TabOrders.[ConfigInstance] = TabConfigurations.[ConfigInstance]) INNER JOIN TabConfigDetails ON TabConfigurations.[Configuration] = TabConfigDetails.[Configuration]) INNER JOIN TabAttributes ON TabConfigDetails.[ConfigIndicator] = TabAttributes.[ConfigIndicator]
And gets me:
OrderNum | Product | Attribute | Value
------------------------------------------
1 | Product1| Product | Bike
1 | Product1| Color | Red
1 | Product1| Accessories| Helmet
1 | Product1| Accessories| Cup Holder
1 | Product1| Size | Large
2 | Product2| Product | Car
2 | Product2| Color | Green
2 | Product2| Color | Orange
2 | Product2| Accessories| Trailer
2 | Product2| Accessories| GPS
2 | Product2| Size | Large
But I would like to get the data formated as below.. but the methods* I have used takes way too long and access crashes..
OrderNum | Product | Attribute | Value
------------------------------------------
1 | Product1| Product | Bike
1 | Product1| Color | Red
1 | Product1| Accessories| **Helmet;Cup Holder**
1 | Product1| Size | Large
2 | Product2| Product | Car
2 | Product2| Color | **Green;Orange**
2 | Product2| Accessories| **Trailer;GPS**
2 | Product2| Size | Large
*Ive mostly attempted utilizing functions, I attempted using GetList function (I created another column CONCAT1 to be used as index.. concatenating ConfigInstance and Attribute then saved the query as DataConfigurations)
GetList: GetList
Is there a better way to structure the query for better performance? It seems when function runs, it reprocesses the entire query each time its triggered.
Here is the query:
SELECT DISTINCT DataConfigurations.OrderNum, DataConfigurations.Product, DataConfigurations.Attribute, GetList("Select Value From DataConfigurations As T1 Where DataConfigurations.CONCAT1 = " & [DataConfigurations].[CONCAT1],"",", ") AS Value_CONCAT
FROM DataConfigurations
This seemed to work only when processing on small amount of orders.. if I tried on entire data set it would run and hangup my computer.
Reference this other question, seems to achieve what you are wanting to accomplish. Performance issues could be result of a improper link (aka duplication) or your PC just needs to be beefier.

Excel VBA to transpose set of rows if value exists in another column

I'm trying to find a way via VB script that will transpose rows from column A into a new sheet but only if there is a value in column B for rows that contain numbers. I have a sheet with ~75K rows on it that I need to do this for, and I tried creating pivot tables which allowed me to get the data into its current format but I need the data to be in columns.
The tricky part of this is that in column A, I only need to look at the rows that are all numbers and not the other rows that have text.
I created a sample sheet to view, where the sample data is in the SOURCE tab and what I want the data to look like in the TRANSPOSED tab.
https://docs.google.com/spreadsheets/d/1ujbaouZFqiPw0DbO78PCnz25OY2ugF1HtUqMg_J7KeI/edit?usp=sharing
Any help would be appreciated.
UPDATE and Answer:
I modified my approach and went back to the original source data which was not part of a pivot table and was able to use a simple match formula between the 2 data sources. So, my original data looked like this:
+----------------+---------+--------+--------------+
| Gtin | Brand | Name | TaxonomyText |
+----------------+---------+--------+--------------+
| 00030085075605 | brand 1 | name 1 | cat1 |
| 00041100015112 | brand 2 | name 2 | cat2 |
| 00041100015099 | brand 3 | name 3 | cat3 |
| 00030085075608 | brand 4 | name 4 | cat4 |
+----------------+---------+--------+--------------+
I had another sheet containing the data I needed to match to in this format:
+----------------+---------+
| Gtin | Brand |
+----------------+---------+
| 00030085075605 | brand 1 |
| 00041100015112 | brand 2 |
| 00041100015098 | brand 3 |
| 00030085075608 | brand 4 |
+----------------+---------+
I created a new column in my source sheet and used a if error match formula:
=IFERROR(IF(MATCH(A14,data_to_match!$A:$A,0),"yes",),"no")
Then copied this formula down for every row, about 75K rows which very quickly added a yes or a no.
+----------------+---------+---------+--------+--------------+
| Gtin | matched | Brand | Name | TaxonomyText |
+----------------+---------+---------+--------+--------------+
| 00030085075605 | yes | brand 1 | name 1 | cat1 |
| 00041100015112 | yes | brand 2 | name 2 | cat2 |
| 00041100015098 | no | brand 3 | name 3 | cat3 |
| 00030085075608 | yes | brand 4 | name 4 | cat4 |
+----------------+---------+---------+--------+--------------+
The final step was to just filter for Yes values and I had all the data that I needed.
My mistake was going to a pivot table first which put the data in a very funky format causing me to have to do a transpose, which wasn't really necessary. Hopefully this can help others....

How to get the cartesian product in MySQL for a single table

Disclaimers first: I'm dealing with a legacy database with a pretty bizarre schema. Plus, I'm a complete SQL noob, so that's not helping either.
Basically, I have a table that has product variations. A good example might be t-shirts. The "generic" t-shirt has a product id. Each type of variation (size, color) has an id. Each value of the variation (red, small) has an id.
So table looks like:
+----+----------+-----------+-------------+----------+------------+
| id | tshirt | option_id | option_name | value_id | value_name |
+----+----------+-----------+-------------+----------+------------+
| 1 | Zombies! | 2 | color | 13 | red |
| 1 | Zombies! | 2 | color | 24 | black |
| 1 | Zombies! | 3 | size | 35 | small |
| 1 | Zombies! | 3 | size | 36 | medium |
| 1 | Zombies! | 3 | size | 56 | large |
| 2 | Ninja! | 2 | color | 24 | black |
| 2 | Ninja! | 3 | size | 35 | small |
+----+----------+-----------+-------------+----------+------------+
I want to write a query that retrieves the different combinations for a given product.
In this example, the Zombie shirt comes in Red/Small, Red/Medium, Red/Large, Black/Small, Black/Medium, and Black/Large (six variations). The Ninja shirt just has the one variation: Black/Small.
I believe this is the cartesian product of size and color.
Those ids are really foreign keys to other tables, so those names/values aren't but wanted to include for clarity.
The number of options can vary (not limited to two) and the number of values per option can vary as well. Ultimately, the numbers are likely to small-ish for a given product so I'm not worried about millions of rows here.
Any ideas on how I might do this?
Thanks,
p.
try this:
select
f.id,
f.tshirt,
color.option_id as color_option_id,
color.option_name as color_option_name,
color.value_id as color_value_id,
color.value_name as color_value_name,
size.option_id as size_option_id,
size.option_name as size_option_name,
size.value_id as size_value_id,
size.value_name as size_value_name
from
foo f
inner join foo color on f.id = color.id and f.value_id = color.value_id and color.option_id = 2
inner join foo size on f.id = size.id and size.option_id = 3
order by
f.id,
color.option_id, color.value_id,
size.value_id, size.value_id;
Looks like distinct can do the trick:
select distinct tshirt
, option_name
, value_name
from YourTable