473,783 Members | 2,287 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Odd SELECT queston???

Hi,

I'm currently learning the ropes with CSS, PHP, MYSQL, Javascript etc...
by redesigning my website as a database driven site.

Okay, so I'm skilled at perl, data manipulation and data analysis and
I've done a fair bit of (non CSS) HTML in the past and know what a
relational database is. However, I'm having problems trying to formulate
a particular MYSQL query (maybe I just don't know the lingo or maybe
I've designed my data incorrectly) and wonder if anyone can shed some
light for me.

Basically, I'm trying to put together a retailers list on my site that
is classified according to the types of products that they sell. The
product list is hierarchically structured (not a flat list) so e.g. one
portion of my retailer type structure looks something like this:

Telecoms:
Mobiles:
Contract
PAYG
SIM Free
Landline:
Services
Handsets
Broadband:
Services
Hardware

Now, I intend to have a menu system on my website which exactly mirrors
my retailer type structure that allows the user to look up a list of
retailers based on the type of product/service that they are after.
However, if the user selects a menu item that relates to an incompletely
specified type (e.g. "telecoms" or "telecoms.mobil es" as opposed to
"telecoms.mobil es.contract") I would like my site to list the superset
of companies that the user's selection relates to e.g. ALL telecoms
related companies or ALL mobile related companies.

Currently, my MYSQL table for retailers simply has a flat list of
(binary valued) ENUM keys, one for each fully-specified LEAF on my
retailer type tree. However I have named these variables in a consistent
manner thus

RMTelMobContrac t
RMTelMobPAYG
RMTelMobSimFree
RMTelLandServic e
RMTelLandHandse t
RMTelBBService
RMTelBBHardware

is the subset of ENUM keys associated with the different types of
telecoms related retailers in the above example.

I was hoping to be able to say, "if I ask for RMTelMob companies, please
return any records where RMTelMob* is 'Y'" where RMTelMob* implies any
key that begins with "RMTelMob".

I know that I can just create extra ENUM keys for each branch in the
tree but I wondered if there was a way of effectively calculating this
on the fly instead, relying on the fact that I adhere to a consistent
naming structure - in essence it looks like I want to find ALL keys that
are extensions of the more general key and then select the record if at
least one of them is marked as true.

Alternatively, is there a better way of designing the data in this table
to make it (a) more consistent with the relational paradigm (b) easier
to query in this manner (I guess (b) would follow from (a) in any case)?

cheers,
RM

Jul 23 '05 #1
5 1811
I've had a good long think about this and wonder if it could be done as
follows...

Firstly, create a table describing the heirarchy of the menu items,
where ALL routes through the menu hierarchy are specified as follows:

Ancestor
Descendent
Route Length

Thus

ALL, RMTel, 1
ALL, RMTelMob, 2
ALL, RMTelMobContrac t, 3
ALL, RMTelMobPAYG, 3
ALL, RMTelMobSIMFree , 3
RMTel, RMTelMob, 1
RMTel, RMTelMobContrac t, 2
RMTel, RMTelMobPAYG, 2
RMTel, RMTelMobSIMFree , 2
RMTelMob, RMTelMobContrac t, 1
RMTelMob, RMTelMobPAYG, 1
RMTelMob, RMTelMobSIMFree , 1

describes the "mobiles" branch of my menu heirarchy:

ALL -- Telecoms ----- Mobiles ----- Contract
| |
| |-- PAYG
| |
| |-- SIM Free
|
|-- Landline ----- Services
|
|-- Handsets

Thus any top level item (such as ALL in this instance) is identifiable
by never existing in the "Descendent s" column and any fully specified
item is identifiable by never existing in the "Ancestor" column.

So, for any particular menu item, all I have to do is look up ALL its
descendents with the maximum route length and, if any exist, check that
at least one of them is marked as "TRUE" in the retailers table, which
still contains a flat list of item types (all the bottom level leaves of
the menu heirarchy). The question is, if the SELECT statement on the
menu heirarchy table returns a list of possible bottom level leaves, how
can I run a query on this list (as field identifiers in the retailers
table) such that at least ONE of the listed fields holds true?

e.g. SELECT * FROM table WHERE [any one of {a,b,c...}] = "TRUE"

where {a,b,c...} is the list returned from the menu heirarchy query

Is this kind of query doable in MYSQL? or do I still not have an
appropriate relational design for my needs?

cheers
RM

Jul 23 '05 #2
Reestit Mutton wrote:
Firstly, create a table describing the heirarchy of the menu items,
where ALL routes through the menu hierarchy are specified
This is exactly the method described in "SQL for Smarties" by Joe Celko
for representing hierarchical structures in an RDBMS. I used it in a
recent project, and it worked great!

For the ancestor and descendant, I made these fields foreign keys into
the "flat" master table of resources. I could get the details for the
retailer by doing a join back to that table.

select r.retailer_name
from retailers r inner join path_enum p
on r.retailer_id = p.descendant_id
where p.ancestor_id = ?

The above fetches all children of ? (which can be specified as a query
parameter).

To find only leaf nodes of the tree, do a further join where the id in
the path_enum never appears as an ancestor of another retailer:

select r.retailer_name
from retailers r inner join path_enum p
on r.retailer_id = p.descendant_id
left outer join path_enum p2
on p.descendant_id = p2.ancestor_id
where p.ancestor_id = ?
and p2.ancestor_id is NULL
The question is, if the SELECT statement on the
menu heirarchy table returns a list of possible bottom level leaves, how
can I run a query on this list (as field identifiers in the retailers
table) such that at least ONE of the listed fields holds true?


I guess you mean that if any one of the retailers has a TRUE value in
some attribute field, then return all of them, otherwise return none of
them? Or return only those that have a TRUE value?

This would provide the latter case:

select r1.*
from retailers r1
where r1.retailer_id in (
select IF(r.some_attri bute = 'TRUE', r.retailer_id, NULL)
from retailers r2 inner join path_enum p
on r2.retailer_id = p.descendant_id
left outer join path_enum p2
on p.descendant_id = p2.ancestor_id
where p.ancestor_id = ?
and p2.ancestor_id is NULL
)

Regards,
Bill K.
Jul 23 '05 #3
Bill Karwin wrote:
Reestit Mutton wrote:
Firstly, create a table describing the heirarchy of the menu items,
where ALL routes through the menu hierarchy are specified

This is exactly the method described in "SQL for Smarties" by Joe Celko
for representing hierarchical structures in an RDBMS. I used it in a
recent project, and it worked great!


Thanks Bill - the early examples in your response demonstrated the
traversal of the tree to find the leaf nodes. However, unless I'm
mistaken, your final example doesn't seem to correspond to my problem.

Basically my problem is as follows...

$query = "SELECT DISTINCT P.RMDescendent
FROM menu_hierarchy P LEFT OUTER JOIN menu_hierarchy P2
ON (P.RMDescendent = P2.RMAncestor)
WHERE P.RMAncestor = '$MenuItem' AND
P2.RMAncestor IS NULL";

Returns a distinct list of fully specified leaf nodes below a selected
menu item, denoted by the variable "$MenuItem" , from my menu hierarchy.
(Thanks - your code was helpful here)

thus, in the following example menu structure,

ALL -- Telecoms ----- Mobiles ----- Contract
| |
| |-- PAYG
| |
| |-- SIM Free
|
|-- Landline ----- Services
|
|-- Handsets
if $MenuItem = "Landline", the above code would return a list of length
2: ["Services", "Handsets"]. Alternatively, if $MenuItem = "Telecoms",
the above code would return a list of length 5: ["Contract", "PAYG",
"SIM Free", "Services", "Handsets"].

Each item in the resulting list should directly correspond to a field
name (for a field of type ENUM with allowable values of 'TRUE' &
'FALSE') in my retailers list. i.e. each record in th eretailers table
contains a single field of type ENUM for each leaf node in the
menu_hierarchy table where the field names are used as values in the
menu_hierarchy table.

What I would like to do is pull all records from the retailers table
where at least one of these fields is marked as TRUE. This would
correspond to e.g. selecting the union of all retailers that sell mobile
related products regardless of whether it is a contract, payg or sim
free handset if I simply choose to select "Mobile" in the menu. However,
if I select "PAYG" in the menu, it will just display those retailers
that sell PAYG mobile handsets.

All retailers are simply marked up for whether or not they offer each
specific type of product. As I may decide to reorganise the menu
structure at a later date I would rather not hard code the relationship
in the retailers table by means of including pre-calculated additional
fields for branches. i.e. the menu_hierarchy table is intended to
describe the structure so that I can find the subset of leaves the
correspond to each possible menu item.

Hopefully this will clarify what I'm after.

cheers,
RM

Jul 23 '05 #4
Reestit Mutton wrote:
Each item in the resulting list should directly correspond to a field
name (for a field of type ENUM with allowable values of 'TRUE' &
'FALSE') in my retailers list. i.e. each record in th eretailers table
contains a single field of type ENUM for each leaf node in the
menu_hierarchy table where the field names are used as values in the
menu_hierarchy table.


Ah, now I understand what you're trying to do. No, you can't do that. ;-)

What you're trying to do is to make a join between data in one table and
the _name_ of a column. So the column in the join criteria would have
to vary on every row of the result set. This is something SQL does not
support; the optimizer must know the tables and columns in the various
clauses, and these tables and columns must not vary (otherwise the
optimizer can't figure out at parse-time necessary things about the
query, such as what indexes might be of benefit).

Instead of storing True/False values in columns for each product
category, you should store the product category names for which a given
retailer has a True value. Make another dependent table for this:

CREATE TABLE retailer_produc t_category (
retailer_id integer not null references retailers,
product_categor y varchar(100) not null
);

So for example, if a given retailer #327 has True values in fields
RMTelLandServic e and RMTelBBService, and False for all the others, you'd
insert two records to retailer_produc t_category:

INSERT INTO retailer_produc t_category VALUES
(327, 'RMTelLandServi ce'),
(327, 'RMTelBBService ');

Don't insert any records for the False values.

Now your categories are data values, not column names, and you can get
the list of retailers you want by performing a join:

Returning the retailers who sell products in a given category is done as
follows:

SELECT DISTINCT R.retailer_name
FROM retailers R INNER JOIN retailer_produc t_category C
ON R.retailer_id = C.retailer_id
WHERE C.product_categ ory = ?

And returning the leaf-nodes of your menu heirarchy who correspond to
retailers who sell products in a given category is the above query
combined with the path enumeration query we did before.

SELECT DISTINCT R.retailer_name
FROM retailers R INNER JOIN retailer_produc t_category C
ON R.retailer_id = C.retailer_id
INNER JOIN path_enum P
ON R.retailer_id = P.descendant_id
LEFT OUTER JOIN path_enum P2
ON P.descendant_id = P2.ancestor_id
WHERE P.ancestor_id = ? AND P2.ancestor_id IS NULL
AND C.product_categ ory = ?

The DISTINCT operation provides your "collapsing ", where if any of the
desired categories applies to the retailer, the retailer is included in
the final result set--once.

Storing the product categories in another table also enables you to
create new product categories without adding columns to your retailer
table. And there's no need for the product category names to be tied to
your menu structure. So it further frees you from hardcoded categories
and menu structure.

Regards,
Bill K.
Jul 23 '05 #5
Bill Karwin wrote:
Reestit Mutton wrote:
Each item in the resulting list should directly correspond to a field
name (for a field of type ENUM with allowable values of 'TRUE' &
'FALSE') in my retailers list. i.e. each record in th eretailers table
contains a single field of type ENUM for each leaf node in the
menu_hierarchy table where the field names are used as values in the
menu_hierarchy table.

Ah, now I understand what you're trying to do. No, you can't do that. ;-)


<SNIP useful solution>

Thanks Bill, my problem is now solved thanks to you. I have also learned
that little bit more about the practicalities of relational database
design. (the theory was never a problem, I was just lacking the
practical experience)

cheers,
RM
--
Boots technology bargains with 10% off + triple advantage card points
e.g. iPod photo 40GB for £281, Nikon Coolpix 4100 for £117
where can I find more details (incl. other bargains & discount codes)?
http://www.users.totalise.co.uk/~lau...tml#0702200501

Jul 23 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
5257
by: JT | last post by:
I have an input form for which I've created a "matrix" for user input. Basically, the user chooses a radio button and then through javascript, a select box is displayed to define a value for that radio option, like so: Choice: (Radio1) type: (select box1) Choice: (Radio1) type: (select box2) Choice: (Radio1) type: (select box3) Choice: (Radio1) type: (select box4) Choice: (Radio1) type: (select box5)
21
5262
by: John Fabiani | last post by:
Hi, I'm a newbie and I'm attempting to learn howto create a select statement. When I use >>> string1='18 Tadlock Place' >>> cursor.execute("SELECT * FROM mytest where address = %s",string1) All works as expected. But >>> numb=10 >>> cursor.execute("SELECT * FROM mytest where clientID = %d",numb) Traceback (innermost last): File "<stdin>", line 1, in ?
3
8103
by: Memduh Durmaz | last post by:
Hi, I'm using DB2 UDB 7.2. Also I'm doing some tests on SQL Server 2000 for some statements to use efectively. I didn't find any solution on Sql Server about WITH ... SELECT structure of DB2. Is there any basic structure on Sql Server like WITH ... SELECT structure?
4
6449
by: point | last post by:
Hello there... I'm a PHP programmer and starting to learn JS... I have a following problem.... I have 3 select boxes! one is hotel one is destination and one is country... if someone clicks selects the country then the destination select box shows the destinations in that country and further if he chooses destination all
1
5525
by: Carl Wu | last post by:
Hi all, I am newcomer in HTML, Javascript, I want to create two select controls S1, S2. There are 3 options: ALL, A, B in S1; When select A in S1, It let you select A1, A2 in S2,
18
4066
by: CJM | last post by:
I'm building a search function for one of my applications. The user has the option to enter a number criteria of criteria, but none are compulsary. I need to be able to build up a query string that includes only the right criteria. The simplest way I have found is something like this: sSQL = "Select field1, field2, etc form table where 1=1" If Request.Form("Criteria1") <> "" then sSQL = sSQL & " and criteria1 = " &...
10
5639
by: serge | last post by:
Using "SELECT * " is a bad practice even when using a VIEW instead of a table? I have some stored procedures that are identical with the difference of one statement in the WHERE clause. If I create a single View and specify also in this View the WHERE clause that is common in these stored procedures, I will have the new stored procecures changed to be like:
1
2970
by: serena.delossantos | last post by:
Trying to insert into a history table. Some columns will come from parameters sent to the store procedure. Other columns will be filled with a separate select statement. I've tried storing the select return in a cursor, tried setting the values for each field with a separate select. Think I've just got the syntax wrong. Here's one of my attempts: use ESBAOffsets go
6
3395
by: Apaxe | last post by:
In the database i have a table with this information: key_id =1 key_desc =43+34+22+12 I want sum the values in key_desc. Something like: SELECT key_desc FROM table But the result of the select was "111" and not "43+34+22+12".
0
9643
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9480
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10313
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10081
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8968
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7494
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5511
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3643
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2875
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.