How can I break up a column from one table with a delimiter into multiple columns in a new table? - plsqldeveloper

I am a self-taught PL/SQL query writer who is relatively new to coding. I know how to conduct basic functions, but have had no formal training and usually google my way to solve any issues I come across. The majority of the time, I am just joining different tables or views in PL/SQL developer to make
I am trying to break up a line from a table based on a series of three delimiters, in this case " > " (spaces included). For example, I want to pull the location "USA > California > Los Angeles" from a table called Locations and break it into three different columns (Country, State, and City). However, the number of repeated delimiters can vary. Sometimes it might just be USA > California and other times it may be USA > California > Los Angeles > Compton.
I want to take this column in one table
[ Location ]
[USA > California > Los Angeles]
and insert three columns it into a different table
[Country ] [State ] [City ]
[USA ] [California ] [Los Angeles ]
So far, I have been able to get around only by using queries and not functions/more advanced techniques. If there's any way to keep this simple and as a query, I'd really appreciate any insight! Again, I use PL/SQL developer so I know that limits certain functions I am able to use.

not too nice but should work for you:
insert into <your table 2> (Country, State, City)
select trim(REGEXP_SUBSTR(Location, '^([^>])*')),
trim(REGEXP_REPLACE(REGEXP_SUBSTR(Location, '>([^>])*'), '>', '')),
trim(REGEXP_REPLACE(REGEXP_SUBSTR(Location, '>([^>])*', 1, 2), '>', ''))
from <your table 1>;
Regards

Related

How to find missing numbers within a column of strings

I'm trying to find unaccounted for numbers within a substantially large SQL dataset and facing some difficulty sorting.
By default the data for column reads
'Brochure1: Brochure2: Brochure3:...Brochure(k-1): Brochure(k):'
where k stands in for the number of brochures a unique id is eligible for.
Now the issue arises as the brochures are accounted for a sample updated data would read
'Brochure1: 00001 Brochure2: 00002 Brochure3: 00003....'
How does one query out the missing numbers, if in the range of number of say 00001-88888 some haven't been accounted next to Brochure(X):
The right way:
You should change the structure of your database. If you care about performance, you should follow the good practices of relational databases, so as first comment under your question said: normalize. Instead of placing information about brochures in one column of the table, it's much faster and more clear solution to create another table, that will describe relations between brochures and your-first-table-name
<your-first-table-name>_id | brochure_id
----------------------------+---------------
1 | 00002
1 | 00038
1 | 00281
2 | 28192
2 | 00293
... | ...
Not mention, if possible - you should treat brochure_id as integer, so using 12 instead of 0012.
The difference here is, that now you can make efficient and simple queries, to find out how many brochures one ID from your first table has, or what ID any brochure belongs to. If for some reason you need to keep the ordinal number of every single brochure you can add a column to the above table, like brochure_number.
What you want to achieve (not recommended): I think the fastest way to achieve your objective without changing the db structure, is to get the value of your brochures column, and then process it with your script. You really don't want to create a SQL statement to parse this kind of data. In PHP that wolud look something like this:
// Let's assume you already have your `brochures` column value in variable $brochures
$bs = str_replace(": ", ":", $brochures);
$bs = explode(" ", $bs);
$brochures = array();
foreach($bs as $b)
$brochures[substr($b, 8, 1)] = substr($b, strpos($b, ":")+1, 5);
// Now you have $brochures array with keys representing the brochure number,
// and values representing the ID of brochure.
if(isset($brochures['3'])){
// that row has a defined Brochure3
}else{
// ...
}

Database schema practical approach

I want to model 2 entities in database: CafeBrand and Cafe. I have pretty much the same properties in both entities:
CafeBrand{
foodDescription,
website,
email,
phone
}
cafe{
foodDescription,
website,
email,
phone
}
So let's say in case of McDonalds all 'cafes' would have the same foodDescription: 'Junk food'. But some other brands might have separate food description for separate cafes('sandwiches', 'drinks only', ...).
Same with website/email/phone properties: cafe might have its own website/email/phone but also it could be using the same website/email/phone for all of them. Quite often the same CafeBrand has one website but different email/phone for its different cafes.
My question is: is it wise to store these properties as it is and then use if/else (in SQL or code) to get a proper description,website,email,phone (if cafe.website == null then use cafebrand.website) or is it better to use relationships to separate tables 'FoodDescription', 'Website' The data won't be written to the database very often and most of the time only select statements will be used.
And if Company has a single cafe. How should this foodDescription/Website be split into CafeBrand/Cafe tables.
As Bill Gregg has mentioned you should probably put all similar data in one table. So you'll receive following structure:
cafe {
foodDescription,
website,
email,
phone,
brand
}
Because of foodDescription, website and so on columns will contains pretty unique values I assume, you won't gain any profit with separation the data into different tables.

Modeling variable depth inheritance in MySQL

I am working on a project where I need to have data inherit at variable depths, and then be able to return any descendants of a particular piece of data. I am working with geographical regions, so I was thinking about having a "Region" table, and have everything from "North America" to individual neighborhoods such as "Bronx". So, if someone types in "North America", they should also receive results for "Bronx" because "Bronx" is a descendant of "North America" by means of the relationship
North America->United States->New York(State)->New York(City)->Bronx
In my DB I was planning on having the Region table link back to itself with a table that specifies a parent/child relationship between Regions. Here is an example of what I would propose:
Any help would be greatly appreciated!
Do you dont need a new table. A foreign key in major table is enough.
This is my approach:
First problem, design data schema: I keep hierarchis with a foreign key to parent row. It is simply. You have an example with hiererchy regions here:
WOE_ID ISO Name Language PlaceType Parent_ID
20069843 "NA" "Oshana" ENG State 23424987
55921113 "NA" "Ondangwa" ENG County 20069843
...
Second problem, retrieve ascendants/descendants: As you explain, problems comes with select: select some region and all descendants os ascendants. To solve this you should to create a new tree table. This table contains pairs: al combination to a person with all they ancestors (and itself):
region( id, name, id_parent)
region_tree( id, id_ancestor, distance )
Noticie that with this structure is easy to query hierarchies. Sample: all descendants of some region:
select region.*, distance
from
region p
inner join
region_tree t
on ( p.id = t.id)
where
id_ancesor = **someregion.id **
You can play with distance to get only sub-regions, sub-sub-regions, ...
Last problem, keep tree: tree must be all time up to data. You should automatize this: a trigger over region or a store procedure for CRUD operations,

USING PDO & MYSQL to get rows compared and switched to columns

I have a Products table, an Imprint table, a Manufacturer table and an ingredients table - along with other tables.
I am currently generating information and use what is called "file_name" as the id (it is a FDA assigned 36-40 digit id that goes with each product). What is happening now is people enter of few letters and the autocomplete dropdown provides the exact spelling. When they click SUBMIT and it brings up all entries that match. If they select a generic product it also includes the "brand" product - if they enter a brand it also includes the generic.
The current display is as follows:
Sold by: Sold using Available Chemical name Data based
name Since: on company
report submitted:
C----- Health Lortab 2011-01-13 Hydrocodone Bitartrate etc 2010-12-07
R—Distributors Hydrocodone 2010-02-18 Hydrocodone Bitartrate etc 2009-12-17
Bitartrate
And Acetaminophen
C-- Health Vicodin 1983-01-07 Hydrocodone Bitartrate etc 2009-11-03
R—Distributors Hydrocodone 2010-07-30 Hydrocodone Bitartrate etc 2010-12-28
Bitartrate
And Acetaminophen
This is working fine. I will be adding a check box on the left which will allow up to 3 of the products to be chosen for comparison and additional information.
THE NEXT STEP:
After they check 1, 2 or 3 items, I want to display like this:
"ALL of the versions of the product you checked contain the following ingredients:"
(Those ingredients common to all chosen products).
ACETAMINOPHEN, CELLULOSE, CORN, CROSPOVIDONE, HYDROCODONE BITARTRATE, MICROCRYSTALLINE, STARCH and STEARIC ACID
(Show the ingredients in each product NOT held in common by all.
End result in COLUMNS)
“IN addition, EACH of the products you chose have the following ingredients:"
COLUMN 1(Product 1) COLUMN 2 (Product 2) COLUMN 3 ( Product 3)
COPOVIDONE MAGNESIUM STEARATE CROSCARMELLOSE SODIUM
CROSCARMELLOSE SODIUM POVIDONE D&C YELLOW NO. 10
D&C RED NO. 27 SILICON DIOXIDE FD&C BLUE NO. 1
D&C RED NO. 30 POVIDONE
HYDRATED SILICA SILICON DIOXIDE
MAGNESIUM STEARATE SUCROSE
End of display
Ingredient table: there are 20,000 rows,46 columns. Each row is a different drug and contains the id, file-name and then the ingredients, Each drug (row) has a different combination and number of ingredients. Unused fields are marked "Null";:
Ingredient columns in each row:
id, file_name, 0_gred, 1_gred, 2_gred, 3_gred, 4_gred, 5_gred, 6_gred, 7_gred, 8_gred, 9_gred, 10_gred, 11_gred, 12_gred, 13_gred, 14_gred, 15_gred, 16_gred, 17_gred, 18_gred, 19_gred, 20_gred (etc. up to 43_gred)
The question is how and what approach to use to get the format I need for the ingredients. I have experience in developing registration systems, I am fairly knowledgeable in PHP and am starting to get use to PDO. My Sql experience is minimal and is basically on a "need to know" basis.
I have wondered whether I should focus on a monster of a MySQL query or more on the php side. I thought about a query giving the ingredients common to all 3 and then subtracting that result from each individual drug list to get Part II but that appears to be quite advanced mysql – especially since I need the data to switch from row to COLUMN layout. Any help?
Another idea was to do a query that concatenated the ingredients of each row and then doing array procedures on the php side. Problems, I am having a hard time finding the right code to pull the ingredients out of each row since the number of “NULL” fields compared to “used” fields varies with each row. (How to count null COLUMNS in PDO query? I’ve tried and get the full count of columns in the table.)
To me, this is a braintwister with several steps. I’m looking for the “magic” MySql Code (if it exists) and or suggestions as to what approach (using php, mysql, PDO) you would pursue.
Your interest/help is appreciated!!
Laura
I figured out a php way to do what I needed. I'm sure there is a faster MySql way. If you know of one please share! Laura
First, I set the Mysql empty values to default to "no_ingre".
Then I did the following code 3 times for the 3 choices:
SELECT 'all the ingredient fields WHERE id=$name_of_id'
$result=$stmt->fetch(PDO::FETCH_ASSOC);
foreach($result as $key => $value) {
if ($value == "no_ingre") unset($result[$key]);
}
FIND THE ingredients COMMON TO ALL:
$same_detect= array_intersect($result, $result2, $result3);
$p_same=(implode(", ", $same_detect));
echo "<br />The below ingredients are in all of the chosen products<br />";
echo $p_same;
To FIND THE ONES NOT COMMON TO ALL: Do the below code 3 times (for each ingredient array):
foreach ($result as $item) {
if (!in_array($item, $same_detect, true)) {
echo ("<tr><td>" . $item . "</td></tr>"); }

DynamicQuery: How to select a column with linq query that takes parameters

We want to set up a directory of all the organizations working with us. They are incredibly diverse (government, embassy, private companies, and organizations depending on them ). So, I've resolved to create 2 tables. Table 1 will treat all the organizations equally, i.e. it'll collect all the basic information (name, address, phone number, etc.). Table 2 will establish the hierarchy among all the organizations. For instance, Program for illiterate adults depends on the National Institute for Social Security which depends on the Labor Ministry.
In the Hierarchy table, each column represents a level. So, for the example above, (i)Labor Ministry - Level1(column1), (ii)National Institute for Social Security - Level2(column2), (iii)Program for illiterate adults - Level3(column3).
To attach an organization to an hierarchy, the user needs to go level by level(i.e. column by column). So, there will be at least 3 situations:
If an adequate hierarchy exists for an organization(for instance, level1: US Embassy), that organization can be added (For instance, level2: USAID).--> US Embassy/USAID, and so on.
How about if one or more levels are missing? - then they need to be added
How about if the hierarchy need to be modified? -- not every thing need to be modified.
I do not have any choice but working by level (i.e. column by column). I does not make sense to have all the levels in one form as the user need to navigate hierarchies to find the right one to attach an organization.
Let's say, I have those queries in my repository (just that you get the idea).
Query1
var orgHierarchy = (from orgH in db.Hierarchy
select orgH.Level1).FirstOrDefault;
Query2
var orgHierarchy = (from orgH in db.Hierarchy
select orgH.Level2).FirstOrDefault;
Query3, Query4, etc.
The above queries are the same except for the property queried (level1, level2, level3, etc.)
Question: Is there a general way of writing the above queries in one? So that the user can track an hierarchy level by level to attach an organization.
In other words, not knowing in advance which column to query, I still need to be able to do so depending on some conditions. For instance, an organization X depends on Y. Knowing that Y is somewhere on the 3rd level, I'll go to the 4th level, linking X to Y.
I need to select (not manually) a column with only one query that takes parameters.
=======================
EDIT
As I just said to #Mark Byers, all I want is just to be able to query a column not knowing in advance which one. Check this out:
How about this
Public Hierarchy GetHierarchy(string name)
{
var myHierarchy = from hierarc in db.Hierarchy
where (hierarc.Level1 == name)
select hierarc;
retuen myHierarchy;
}
Above, the query depends on name which is a variable. It mighbe Planning Ministry, Embassy, Local Phone, etc.
Can I write the same query, but this time instead of looking to much a value in the DB, I impose my query to select a particular column.
var myVar = from orgH in db.Hierarchy
where (orgH.Level1 == "Government")
select orgH.where(level == myVariable);
return myVar;
I don't pretend that select orgH.where(level == myVariable) is even close to be valid. But that is what I want: to be able to select a column depending on a variable (i.e. the value is not known in advance like with name).
Thanks for helping
How about using DynamicQueryable?
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Your database is not normalized so you should start by changing the heirarchy table to, for example:
OrganizationId Parent
1 NULL
2 1
3 1
4 3
To query this you might need to use recursive queries. This is difficult (but not impossible) using LINQ, so you might instead prefer to create a parameterized stored procedure using a recursive CTE and put the query there.