MySQL: Subqueries for normalized databases - php

I've spent a lot of time on Google searching for this and also landed on Stackoverflow a few times, but I couldn't figure out how to fulfill my needs.
It might be pretty ease for most of you, but I just can't get it to work.
Let's assume I have this table:
item_data
And another one:
vendor_data
What I want to get is a query where I'm selecting one item from the first table, and the query should replace the vendor_id with the respective name specified in the second table - only for my output of course.
The logic is very easy, I think, but I just can't create a proper query.
Like:
I'm selecting the item with the id 2 from the table item_data, then I get the vendor_id that is also specified in item_data, this vendor_id is being looked up in vendor_data -> vendor_id (3) and the right vendor_name (CompanyZ) is brought back as my result.
I'd really appreciate your help, thanks!
Andy

It sounds like you are just wanting a simple join
SELECT i.item_id, i.item_name, v.vendor_id, v.vendor_name <-- select whatever fields you need here
FROM item_data AS i
INNER JOIN vendor_data AS v ON i.vendor_id = v.vendor.id
WHERE i.item_id = ? <-- specify item_id for lookup here

Related

Joins not working in SQL Code not joining corectly strange errors occurring

I have been trying to get this code working for almost six hours an I have done almost six hours worth of research.
Originally this code was to be outputted from a database through PHP to a CSV file..
All I am trying to do is have three different tables and have them all joined together by their order_ID
Every time I keep trying to do this in PHP my admin either the code comes out weird in the output is not joining correctly or is giving some sort of strange error. Any help that anyone could figure out what is going on with this would be greatly appreciated
SELECT
oc_order.store_url,
oc_order.order_id,
oc_order.firstname,
oc_order.lastname,
oc_order.email,
oc_order_option.order_id,
oc_order_option.name,
oc_order_option.value,
oc_order_product.order_id,
oc_order_product.name,
oc_order_product.model,
oc_order_product.quantity
FROM oc_order, oc_order_option , oc_order_product
ORDER BY oc_order.order_id,oc_order_option.order_id,oc_order_product.order_id
As mentioned, you are missing your ON clauses. When you are using multiple tables in a SQL query, you have your LEFT table (first table in from clause) being JOINed to the second (right table). The "ON" clause tells how table 1 is related to table 2. And in your case, you have a table 3. Is this a relationship between table 1 to 3 or from table 2 to 3. I will update the query, you will need to fill in the blanks a bit since you have not shown structures. Also, using table aliases makes code more readable, especially if table names get long. You'll see in a moment.
SELECT
o.store_url,
o.order_id,
o.firstname,
o.lastname,
o.email,
oOp.order_id,
oOp.name,
oOp.value,
p.order_id,
p.name,
p.model,
p.quantity
FROM
oc_order o
JOIN oc_order_option oOp
on o.order_id = oOp.order_id
JOIN oc_order_product p
on o.order_id = p.order_id
ORDER BY
o.order_id
Notice the abbreviated aliases for the table names "o" for oc_orders, "oOp" for oc_order_option and "p" for oc_order_product
Again, YOU need to confirm the "ON" clauses on the left-table is associated with the right table. I have worked with manufacturing in the past and have seen that someone orders. Purchases a product, and that product has options, so Is there something on the order's detail line for the specific product that has an ID to the order OPTIONS table. That is where you probably need to focus. Again, other systems I have had, would have had a hierarchy something like
Order
Customer (who ordered)
OrderDetails (what of multiple products were ordered)
Product ( per orderDetail, what was the product)
ProductOption (color,size,etc)
See the hierarchical representation? In this scenario, you dont go just from Order table to the Product option. You have to get to the details to the product to the product's option. Anyway, HTH

Add Column to one Table that is COUNT of another

I have a list of subscribers in table Subscribers. Every time they receive a copy of their subscription, a new record is created in Subscriptions_Fulfilments for each Subscribers.ID.
I can create a table showing each Subscriber ID and the number of copies they received with the following query:
SELECT Sub_ID, COUNT(Sub_ID) fcount FROM `Subscriptions_Fulfilments`
GROUP BY Sub_ID
But I need to create a compound query that returns Subscribers along with a column showing the COUNT(Sub_ID) of Subscriptions_Fulfilments.
So I have two questions:
A) How would you make a query to create a table that shows each Subscriber and the number of times they've received their subscription, based on the COUNT of that Subscriber's ID in Subscriptions_Fulfilments?
B) I'm operating under the assumption that a single MySql query accomplishing this would be more efficient than, say, running two queries, the one above and a SELECT * FROM Subscriptions, and combining the resulting arrays in PHP. I have a feeling I know the answer but I'd like to positively learn something new today.
Unfortunately, after too many tries, I'm clearly not good enough at queries for this and I have very little past the above query to show for it. I apologize if this ends up being a dup, I searched long and hard before asking, but it's quite difficult to search precisely for Query help...
Here is a simple example showing the Subscribers ID and the no of subscription they have received. Hope it helps.
Step 1: select the ids from the Subscriber table
Step 2: select the no of counts of subscriptions received by each subscriber.
Step 3: Join both the table ON the basis of ID.
SELECT SubId, noSub FROM
Subscribers sb JOIN (SELECT SubId AS sid, COUNT(*)AS noSub FROM Subscriptions_Fulfilments GROUP BY SubId)AS ss ON sb.SubId = ss.sid
One of the big advantages of a relational database is the ability to do joins and combinations of the data in your tables in a way that allows for this functionality without having to actually store it in a separate table.
You can accomplish this with a subquery like this:
SELECT Subscribers.name, fulfilments.count FROM Subscribers
INNER JOIN (
SELECT id, count(*) as count FROM Subscriptions_Fulfilments
GROUP BY Sub_Id
)fulfilments ON subscribers.id = fulfilments.id
This might not be 100% what you're looking for and I might have messed up your names, but hopefully this will start to get you in the neighborhood of being correct?
Simply try execute this query:
Select distinct Sub_ID, count from (SELECT Sub_ID, COUNT(Sub_ID) fcount FROM Subscriptions_Fulfilments
GROUP BY Sub_ID);

Getting ID related to another ID in table then using the ID to get information from another table

I am going to try and explain this the best way I can. I have a table called albumAccess which has the following fields : id, albumID, userID, and permission.
Next I have another table that holds information for each album based off of the albumID.
I want to know how I can use the userID to get all of the album information. I have been researching joins and php arrays but not sure how to go about doing it.
Any help will be appreciated!
Its hard without a syntax to work with but i think something like this could work.
SELECT
tablea.*,
tableb.*
FROM albumaccess tablea
JOIN albuminfo tableb ON tablea.AlbumId=tableb.AlbumId
WHERE tablea.UserId='theuserid'
This will JOIN rows matching on AlbumId.
I am taking the another table name as albumDetails that holds information for each album based off of the albumID.
select albumAccess.*, albumDetails.* from albumAccess, albumDetails where
albumAccess.albumID=albumDetails.albumID and
albumAccess.userID=YOUR_REQUIRED_USER_ID
I think this is what you looking for.
SELECT * FROM users u, albuminfos ai, albumaccesses aa WHERE aa.user_id=u.id

mySQL logic: output of table join not correct

I am trying to query two tables: finished_events and flagged_events. 1st of all I need everything related to the company_id so
SELECT *
FROM finished_events
WHERE company_id=$id
ORDER by schedule, timestamp
I then changed this to:
SELECT * FROM finished_events
INNER JOIN flagged_events
ON finished_events.company_id=flagged_events.company_id
WHERE finished_events.company_id=$id
ORDER by finished_events.schedule, finished_events.timestamp
I have tried using FULL JOIN, LEFT JOIN, and RIGHT JOINs all unsuccessful. Specifically what I want is to get is a combined effort of the following code:
$sql = "SELECT *
FROM finished_events
WHERE company_id=$id
ORDER by schedule, time_stamp";
$flagged_sql = "SELECT *
FROM flagged_events
WHERE company_id=$id
ORDER by schedule, time_stamp";
The tables are a bit different so UNION won't work here. I can post dummy database entries but this won't be of too much help as I need all from both tables. The 2 links between the tables would be the company_id and the schedule columns. Essentially what is going on behind the scenes is timestamps being put into a different table to which I then process either into finished_events or flagged_events. Flagged events will need the user to do something about it until it is a finished event. So this script is generating the data for the GUI, hence why I need to query both tables and create an associative array of customer details then an array of events (from these 2 tables). So creating the assoc_array is no problem I just need to get this query to spit out all the events and order them correctly. Let me know if you need anything specific to solve this one, thanks :)
EDIT
SQL Fiddle: http://sqlfiddle.com/#!2/d4c30/1
this almost fixes it but not quite right, it repeats entries at the bottom
If I understood correctly, this may be useful for you:
SELECT a.* FROM (
SELECT *, 'finished' as event_type FROM finished_events
UNION
SELECT *, 'flagged' as event_type FROM flagged_events) a
ORDER BY a.schedule, a.time_stamp

Using PHP, how do I query this mySQL database across these three tables?

I hate to submit a new question, but everyone else has some slight thing that is different enough to make this one seem necessary to ask.
Users are to type in a vendor name, and then see all the "kinds" of things they have bought from that company, in a list, sorted by the lowest-inventory-on-hand.
Summary:
I have three tables.
There are more fields than these, but these are the relevant ones (as far as I can tell).
stuff_table
stuff_vendor_name *(search this field with $user_input, but only one result per lookup_type)*
lookup_type
lookup_table
lookup_type
lookup_quantity (order by this)
category_type
category_table
category_type
category_location (check if this field == $this_location, which is already assigned)
Wordier Explanation:
The users are searching for a value that is contained only in the stuff_table -- distinct stuff_vendor_name values for each lookup_type. Each item can be bought from multiple sources, the idea is to see if any vendor has ever sold even one of any type of item before.
But the results need to be ORDER BY the lookup_quantity, in the lookup_table.
And importantly, I have to check to see if they are searching the correct location for these categories, located in the category_table in the category_location field.
How do I efficiently make this query?
Above, I mentioned the variables that I have:
$user_input (the value we are searching for distinct matches in the stuff_vendor_name field) and $current_location.
To understand the relationship of these tables, I will use an example.
The stuff_table would have dozens of entries with dozens of vendors, but have a lookup_type of, say, "watermelon," "apple," or "cherry."
The lookup_table would give the category_type of "Jellybean." One category type can have multiple lookup_types. But each lookup_type has exactly one category_type.
You are not sharing much about the relationships, but try this:
SELECT *
FROM stuff_table st
LEFT JOIN lookup_table lt
ON st.lookup_type = lt.lookup_type
LEFT JOIN category_table ct
ON lt.category_type = ct.category_type
AND ct.category_location = $this_location
GROUP BY st.lookup_type
ORDER BY lt.lookup_quantity
WHERE st.stuff_vendor_name = $user_input
From a first glance at it you could use foreign keys in your tables to make link between them or using the LEFT JOIN mysql command to make abstraction of another linked table.
The only example I can think of is on a Doctrine pattern, but I think you'll get what I'm saying:
$q = Doctrine_Query::create()
->from('Default_Model_DbTable_StuffTable s')
->leftJoin('s.LookupTable l')
->leftJoin('s.CategoryTable c')
->orderBy('l.lookup_quantity DESC');
$stuff= $q->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
I made a nested query instead.
The final code looks like this:
$query_row=mysql_query(
"SELECT DISTINCT * FROM table_a WHERE
field_1 IN (SELECT field_1 FROM table_b WHERE field_2 = $field_2)
AND field_3 IN (SELECT field_3 FROM table_c WHERE field_4 = $field_4)
ORDER BY field_5 DESC
");
This was incredibly simple. I just didn't know you could do a nested query like that.
I read it was "bad form" because it makes some kind of search optimization not as good as it could be, so be careful using nested select statements.
However for me, it seemed to actually be significantly faster.

Categories