I have a table of Products that looks like so:
| id | Description | Price |
| 1 | dinglehopper | 2.99 |
| 2 | flux capacitor | 48.99 |
| 3 | thing1 | 48.99 |
And so on...
Then I have an OrderLineItem table which, as you can guess, links each item in an order to the product:
| id | productID | OrderID |
| 43 | 1 | 12 |
| 44 | 2 | 12 |
| 52 | 3 | 15 |
So, as you can see, order #12 contains a dinglehopper and flux capacitor. How can I get this information in a single query? I just want ALL the products associated with a given OrderID in the OrderLineItem table.
May be by
select p.description,p.id,o.irderId
from
`orderLineItem` o, `product` p
where
p.id = o.productId;
or
select p.description,p.id,o.irderId
from `orderLineItem` o
join `product` p
on p.id = o.productId;
LEFT JOIN :)
http://www.w3schools.com/sql/sql_join_left.asp
#Pete About "single" query part, you should make VIEW from this join, if really going to use a lot.
Related
I have 1 master_table and 2 sub_tables. I want the join the 3 columns together (but the problem is the 2 sub_tables do not have any column that share the same value) and then SELECT * based on 2 different columns from the 2 sub_tables.
I've searched and tried many ways of coding, but couldn't find a solution.
SELECT *
FROM (master INNER JOIN sub_1 ON master.id=sub_1.id WHERE sub_1.column_1 = 'Y')
AND (master INNER JOIN sub_2 ON master.id=sub_2.id WHERE sub_2.column_2 = 'Y')
ORDER BY master.id
++++++++++++++++++++++++++++++++++++++++++++++++++
* Finally, solved. See the solution at the bottom of this post. *
++++++++++++++++++++++++++++++++++++++++++++++++++
===========
Edit: explain more about my data, problem and MySQL code
I have 3 tables stored in MySQL as follow
Master_table: regist
------------------------------------------
| reg_no | firstname | lastname | submit |
------------------------------------------
| 1 | first_A | last_A | N |
| 2 | first_B | last_B | A |
| 3 | first_C | last_C | P |
| 4 | first_D | last_D | P |
| 5 | first_E | last_E | A |
| 6 | first_F | last_F | N |
| 7 | first_G | last_G | N |
| 8 | first_H | last_H | A |
------------------------------------------
Sub_1: sub_A Sub_2: sub_P
------------------------------ ------------------------------
| reg_no | A_title | reply_A | | reg_no | P_title | reply_P |
------------------------------ ------------------------------
| 2 | 222 | Y | | 3 | 333 | N |
| 5 | 555 | N | | 4 | 444 | Y |
| 8 | 888 | Y | ------------------------------
------------------------------
I want to create a query that gives result like this
----------------------------------------------------------------------------------
| reg_no | firstname | lastname | submit | A_title | reply_A | P_title | reply_P |
----------------------------------------------------------------------------------
| 2 | first_B | last_B | A | 222 | Y | | |
| 8 | first_H | last_H | A | 888 | Y | | |
| 4 | first_D | last_D | P | | | 444 | Y |
----------------------------------------------------------------------------------
or
-----------------------------------------------------------
| reg_no | firstname | lastname | submit | title | reply |
-----------------------------------------------------------
| 2 | first_B | last_B | A | 222 | Y |
| 8 | first_H | last_H | A | 888 | Y |
| 4 | first_D | last_D | P | 444 | Y |
-----------------------------------------------------------
$sql = "SELECT *
FROM (regist INNER JOIN sub_A ON regist.reg_no = sub_A.reg_no WHERE sub_A.reply_A = 'Y')
AND (regist INNER JOIN sub_P ON regist.reg_no = sub_P.reg_no WHERE sub_P.reply_P = 'Y')
ORDER BY regist.reg_no";
Expected outcome:
ECHO personal data of all registrants who got reply as 'Y'
if($row['submit']=="A") $title = $row['A_title'];
elseif($row['submit']=="P") $title = $row['P_title'];
$result = mysql_query($sql) or die(mysql_error());
while($row = mysql_fetch_array($result))
{
echo $row['reg_no']." / ".$row['firstname']." ".$row['lastname']." / ".$title."<br>";
}
Problem: my SELECT code resulted in error. The code from #GMB and #Rogue didn't error, but echo give nothing.
If it is not possible to code a query as I want, I will just modify the column names (sub_1.reply_A and sub_2.reply_P) to be the same and change the input code in other webpages. However, it would be best if there is a way because I don't know whether the 'reply' columns were used somewhere else.
========================
Solution: a little modification from #Rogue code
SELECT *
FROM master
LEFT OUTER JOIN sub_1
ON master.id=sub_1.id
LEFT OUTER JOIN sub_2
ON master.id=sub_2.id
WHERE sub_1.column_1 = 'Y'
OR sub_2.column_2 = 'Y'
ORDER BY master.id
Do you just want simple JOINs between these 3 tables ?
SELECT m.*, s1.*, s2.*
FROM master m
INNER JOIN sub_1 s1 ON m.id=s1.id AND s1.column_1 = 'Y'
INNER JOIN sub_2 s2 ON m.id=s2.id AND s2.column_2 = 'Y'
ORDER BY m.id;
If you have master records that may not exist in both sub tables, you can switch to LEFT JOIN to avoid filtering them out.
Guidelines :
typical syntax is SELECT ... FROM table1 INNER JOIN table2 ON ... INNER JOIN table3 ON...
better put all conditions related to a JOINed table in the ON clause of the join rather than in the WHERE clause
avoid SELECT * : be specific about the columns you want to select
use table aliases to make the query easier to read
You're a little off syntactically:
SELECT *
FROM master
LEFT OUTER JOIN sub_1
ON master.id=sub_1.id
LEFT OUTER JOIN sub_2
ON master.id=sub_2.id
WHERE sub_1.column_1 = 'Y'
AND sub_2.column_2 = 'Y'
ORDER BY master.id
Personally I would recommend not using SELECT * and only grabbing the data you will need. As for determining what join to use, I like to link to CodingHorror's blog post in these times.
Edit: swapped INNER to LEFT OUTER, per OP's update
I have the following problem: I have a table import_data
The table is enriched something like this
| id | profile_id | sku | vendor | price | importRun |
| 1 | 39 | 123 | myVen | 2.0 | 1 |
| 2 | 39 | 456 | myVen | 2.0 | 1 |
| 3 | 39 | 123 | myVen | 3.0 | 2 |
What I need to get is an output of all elements, but only once. Every sku must be unique. To make it even worse, I need the newest data, if they are redundant.
My output should be like this:
| id | profile_id | sku | vendor | price | importRun |
| 2 | 39 | 456 | myVen | 2.0 | 1 |
| 3 | 39 | 123 | myVen | 3.0 | 2 |
Short Summary about the structure:
ID = PK
sku = a unique identifier for an article
importRun = Needed for comparision.
So, to explain it: I have an import-script, which reads a given CSV-file and imports all articles listed in it. I get this CSV-file in a regular period (once a week). I need to collect all data and save it, to create a price-evolution later on.
After every Import, I increment the number of importRun, so that no information is lost (remember, I can't use REPLACE INTO or INSERT IGNORE.
Now, when I export it, I need the newest Data, if a SKU occures multiple times. In this case, the SKU 123 is inserted 2 times on 2 different runs. That means, since my newest Run had the number 2, I need this tupel (and ignore the first one).
When I work with DISINCT, it would still output the same table, since they aren't distinct at all, because importRun differs.
I should be able to use GROUP BY, but I couldn't figure out which value will be taken, the first- or the last one? (importRun 1 or 2)
Update 1
Followed by the idea of #mitkosoft, I tried the following:
SELECT DISTINCT t1.*
FROM import_data t1
INNER JOIN import_profiles imp on t1.profile_id = imp.id
INNER JOIN (
SELECT DISTINCT sku, MAX(importRun) AS importRun
FROM import_data
GROUP BY sku ) t2
ON t1.sku = t2.sku
WHERE imp.creditornr = 73329
AND t1.vendor = 'rackmountit'
AND t1.importRun = t2.importRun
** Update 2 **
I added the complete Structures for all tables, which are relevant.
Import-Data:
|
Import-Profiles
But i still get duplicates :/
All you need to do is to determine MAX(importRun) for each sku:
SELECT
t1.*
FROM
import_data t1
INNER JOIN (
SELECT sku, MAX(importRun) AS importRun FROM import_data GROUP BY sku
) t2
ON t1.sku = t2.sku
AND t1.importRun = t2.importRun
Output is:
+----+------------+-----+--------+-------+-----------+
| id | profile_id | sku | vendor | price | importRun |
+----+------------+-----+--------+-------+-----------+
| 2 | 39 | 456 | myVen | 2.0 | 1 |
| 3 | 39 | 123 | myVen | 3.0 | 2 |
+----+------------+-----+--------+-------+-----------+
2 rows in set
Perhaps you could join on the same table where sku = sku
I've a mysql table named PRODOTTO structured in this way
+----+-----------+-------------+----------+--------+
| id | categoria | prodotto | quantita | prezzo |
+----+-----------+-------------+----------+--------+
| 1 | bar | Maxibon | 887 | 2.00 |
| 2 | bar | Limonata | 21 | 1.50 |
| 3 | bar | Coca Cola | 70 | 1.50 |
| 4 | bar | chupa chups | 30 | 0.60 |
| 5 | bar | pirulo | 79 | 1.00 |
+----+-----------+-------------+----------+--------+
and another one named CONSUMAZIONI
+----+----------+----------+--------+-----------------+--------+
| id | prodotto | quantita | prezzo | totale_parziale | status |
+----+----------+----------+--------+-----------------+--------+
| 1 | Maxibon | 1 | 2.00 | 2.00 | open |
| 2 | pirulo | 6 | 1.00 | 6.00 | open |
+----+----------+----------+--------+-----------------+--------+
I'd like to merge this to tables and obtain a unique table like this
+----+----------+----------+----------------------+--------+----------------+--------+
| id | prodotto | quantita | quantita_disponibile | prezzo | totale_parziale | status |
+----+----------+----------+----------------------+--------+-----------------+--------+
| 1 | Maxibon | 1 | 887 | 2.00 | 2.00 | open |
| 2 | pirulo | 6 | 79 | 1.00 | 6.00 | open |
+----+----------+----------+----------------------+--------+-----------------+--------+
So the new table is the combiantion fo the table CONSUMAZIONI and the column "quantita" of the prodotto's table.
On this new table I will do a query like this
SELECT * FROM...
Try this:
CREATE TABLE Fusione AS
(SELECT p.id,p.prodotto,c.quantita,p.quantita AS quantita_disponibile,p.prezzo,c.totale_parziale,c.status
FROM Prodotto P, Consumazione c
WHERE p.id=c.id
)
Also consider to restucture your schema, because you have redundancy in the two tables. Indeed, table Consumazioni should be a relation on table Prodotto. So Consumazioni should be someting like:
id_prodotto | quantità | status
The other information are available by joining the two tables and performing some basic mathematical operations on data (e.g., totale_parziale is prezzo*quatita).
What you can do in PHP, or rather in MySQL is Create a VIEW; so you don't always have to make a JOIN.
You can create a view for those tables, like the following:
CREATE VIEW prodConsumption AS
SELECT
p.prodotto, c.quantita, p.quantita AS quantita_disponibile, p.prezzo, c.totale_parziale, c.status
FROM
PRODOTTO p
INNER JOIN
CONSUMAZIONI c ON p.prodotto=c.prodotto
Ofcourse, you should look into your table, joining by name is horrible, and your IDs doesn't seem to match.
Afterwards, you can do as you wanted:
SELECT * FROM prodConsumption
You can create a VIEW for this:
CREATE VIEW view_prodotto_consumazinoni AS
SELECT
c.id AS id,
c.prodotto AS prodotto,
c.quantita AS quantita,
p.quantita AS quantita_disponibile,
c.prezzo AS prezzo,
c.totale_parziale AS totale_parziale,
c.status AS `status`
FROM consumazinoni c INNER JOIN prodotto p ON c.prodotto=p.prodotto;
This procudes exactly the output you want:
SELECT * FROM view_prodotto_consumazinoni;
id prodotto quantita quantita_disponibile prezzo totale_parziale status
1 Maxibon 1 887 2 2 open
2 pirulo 6 79 1 6 open
The advantage of such a VIEW is that you can define it once and then use it just like an ordinary table without having to think about the JOIN done all the time. It is synchronized with the changing data in the two base tables, so always up to date.
I set up a sql fiddler for you, so that you can play around a bit:
http://sqlfiddle.com/#!9/76a43/1
Have fun!
I have three tables group_sentences, group_sentences_attributes and group_senteces_categories.
I have an attributes array which I am using in query with IN (after implode).
Then I have one category ID because they are stored recursively, so no need for an array.
I need to select one group number where is the biggest match for $attributesArray and of course category too.
Here is table group_sentences_attributes
+-----+-------+-----------+
| id | group | attribute |
+-----+-------+-----------+
| 1 | 1 | 3564 |
| 2 | 1 | 3687 |
| 3 | 1 | 3689 |
| 4 | 2 | 3687 |
| 5 | 2 | 3564 |
+-----+-------+-----------+
Here is group_sentences_category
+-----+-------+----------+
| id | group | category |
+-----+-------+----------+
| 1 | 1 | 1564 |
| 2 | 1 | 1221 |
| 3 | 1 | 1756 |
| 4 | 2 | 1358 |
| 5 | 2 | 1125 |
+-----+-------+----------+
Here is my query, but I am afraid that it won't do the job done.
SELECT group_categories.group
FROM group_categories, group_attributes
WHERE group_categories.category = '$category'
AND group_attributes.attribute IN ($attributesArray)
GROUP BY group_categories.group
ORDER BY count(group_attributes.attribute)
Any help would be appreciated, thanks.
First, the table in your query do not match the tables in the question. I am guessing they are simply missing the "sentence". Then, you have no join clause. Simple rule: Never use commas in the from clause.
group is a lousy name for a column, because it is a keyword in SQL. The following may be what you are looking for:
SELECT gc.groupid
FROM group_sentences_attributes sa JOIN
group_sentences_category sc
ON sa.groupid = sc.groupid
WHERE sc.category = '$category' AND
sa.attribute IN ($attributesArray)
GROUP BY sa.groupid
ORDER BY count(sa.attribute);
If you only want one row, then add LIMIT 1 to the end.
I have 3 tables,
itemmaster
|--------|----------|
| id | name |
|--------|----------|
| 1 | Pizza |
|--------|----------|
| 2 | Burger |
|--------|----------|
| 3 | Pepsi |
---------------------
order
|--------|----------|
|orderid | date |
|--------|----------|
| 1 | 1-1-11 |
|--------|----------|
| 2 | 2-1-11 |
|--------|----------|
| 3 | 3-1-11 |
---------------------
orderdetails
|--------|-------------|---------|---------|
| id | orderid |itemid |quantity |
|--------|-------------|---------|---------|
| 1 | 1 | 1 | 10 |
|--------|-------------|---------|---------|
| 2 | 1 | 2 | 20 |
|--------|-------------|---------|---------|
| 3 | 2 | 1 | 10 |
-------------------------------------------
I want to join these 3 tables to get quantity of items of an order that placed on a particular date.
What I have tried is
$this->db->from('itemmaster');
$this->db->join('orderdetails', 'orderdetails.itemid= itemmaster.id','left');
$this->db->join('order', 'order.orderid= orderdetails.orderid');
$this->db->where('order.date',"1-1-11");
$query = $this->db->get();
I got Result as,
Pizza------ 10
Burger------10
What I want is,
Pizza-------10
Burger------20
Pepsi-------0
If changing the all the joins to left joins, you can always do it in two separate query and do a union between the two of them. One would get all the lines that actualy have a quantity and the other would get the rests and put them toguether.
It would look a bit like this. there might be some synthax error, but you'll have to rewrite it in php anyway:
p.s. to add up the quantities, you can use sum()
Select itemmaster.name, orderdetails.quantity from itemmaster
left join orderdetails on orderdetails.itemid = itemmaster.id
left join order on order.orderid = orderdetails.orderid
where order.date = '1-1-11'
group by itemmaster.name
Union
Select itemmaster.name, '0' as quantity From itemmaster
except (Select itemmaster.name, orderdetails.quantity from itemmaster
left join orderdetails on orderdetails.itemid = itemmaster.id
left join order on order.orderid = orderdetails.orderid
where order.date = '1-1-11'
group by itemmaster.name)
group by itemmaster.name
hope this helps ! good luck