Select equal values from column with inner join (sql) - mysql

I am pretty new to SQL, so please dont go too hard on me :(
I have got two tables - "cart" and "orders". In the "cart" table are all the things a random user has ordered - in this case these few rows (with the column names above):
session_id - product_id - product - product_name - price - quantity
1 - 1 - Table - Something - 10.00 - 1
1 - 2 - Chair - SomethingNew - 20.00 - 1
2 - 2 - Chair - SomethingNew - 20.00 - 1
I want to write a statement that selects all the orders with the same session_id - in this case the number 1 - and copy it into the "orders" table, because all the items with the same session id should be labeled as one big order - but i don't want to hard code it (with select and session_id=1 for instance)...
This is what i have got so far for my selection:
I tried using a inner/self join, so that i can check if the values are the same
SELECT * from cart JOIN cart AS cartB
WHERE cart.session_id = cartB.session_id
GROUP BY cart.session_id;
But this currently gives me the following rows as solution:
session_id - product_id - product - product_name - price - quantity
1 - 1 - Table - Something - 10.00 - 1
2 - 2 - Chair - SomethingNew - 20.00 - 1
Instead of (what i would have wanted):
session_id - product_id - product - product_name - price - quantity
1 - 1 - Table - Something - 10.00 - 1
1 - 2 - Chair - SomethingNew - 20.00 - 1
EDIT: I know, the 2nd and 3rd rows are pretty similar. But thats exactly why the session id is very important in this case, and why i'd like to make it work.
What am i doing wrong? Is the inner join even needed? I am really having some problems with the statment since i am a huge beginner here.. but my code would make sense to me.. :(
Big thanks to everybody who takes his time to read this (and maybe even help)!

At the moment I see here 2 options:
Either your PROGRAM passes to SQL the session IDs for orders that you want to copy to orders table, -- which would be normal in any webshop.
In which case you have to get the correct session_id= from your program and pass it to your SQL query as a parameter, eg. in PHP.
Or you want to copy ALL session_id'd cart contents into orders. In which case it is even simpler, without any WHERE: INSERT INTO order SELECT * FROM cart;
If you want something else, you should specify, how it is determined WHICH session_id's need to be copied from cart to orders.
UPD. And you are right, the JOIN in your example doesn't appear to do anything useful.

Related

Database design will not support entry of products.

I have the database design below:
table design
basically, I need to be able to input products that have the following columns:
id, area, category, name
The problem is that if I create the database to the spec in the image above, then wouldn't that still cause repeats in the table catalogue? which would be against the normal forms.
Also it means that the data in catalogue would just be numbers aka references to the other tables. Is there a solution to this issue? as I imagine any catalog site that has a db back-end would have the same issue.
Here is an example that is the same issue just different sinorio if it helps:
I have a product catalog that sells laptops and TVs, do I make a table that has the type of device? because that would look like this:
id - name - type - etc
1 - acerP - laptop - null
1 - acerP - laptop - null
1 - acerP - TV - null
Notice how 'laptop' could get repeated 100s of times, normally you would create a new table that has just:
u_id - type
101 - laptop
102 - TV
Then simply join then in the query, but then you would have in the device table:
id - name - type - etc
1 - acerP - 101 - null
1 - acerP - 101 - null
1 - acerP - 102 - null
but now you are repeating the number references.
Am I missing something here, or is this normal?
This is norma, only foreign keys would be repeated in your proposed structure, which is allowed by the 1NF:
First normal form enforces these criteria:
- Eliminate repeating groups in individual tables.
...
Groups means a combination of columns. The same category may appear more than once in catalogue, but not, for example the couple (category, area).

Without using store procedure, is there any way that we can control Constraints of return Qty over the total Qty in OrderLine (MySQL)?

Ok, generally, an order system will have these tables:
1. Order table
OrderID - OrderDate....
2 - 12/11/2014
...
2.OrderLine table
OrderLineID - OrderID - Item ID - ItemName - Total Qty....
2 - 2 - 5 - iPhone - 3
....
3. Return table
ReturnID - OrderLineID - Return Qty
2 - 2 - 1
Look at the above table we saw the customer generated an order (orderID=2), he bought 3 iPhone (OrderLineID=2 with total Qty=3), but then later he returned 1.
My question is, for the same OrderLine, can we force the Return Qty column in Return table must be <= TotalQty column in OrderLine Table. For ex, in the above example, if someone inserts the Return Qty=4 in return table for orderline=2, the system will generate an constraint error.
ReturnID - OrderLineID - Return Qty
2 - 2 - 4 --> system should generate an error cos 4 >3
In Return table, we control the foreign key by using add foreign key (orderLineID) references OrderLine(orderLineID)
But then how can we do the similar thing for the return Qty without using Stored procedure?
You need to create 2 triggers to validate the Return Qty column:
BEFORE INSERT and BEFORE UPDATE. Take a look at this article http://cvuorinen.net/2013/05/validating-data-with-triggers-in-mysql/

MYSQL Query matching column names to rows in another table

I have two tables in MYSQL, one contain a list of options a customer can pick from and the other has the cost of the options. I would like a view that returns the cost of each customers option set. For my example I'll use the analogy of buying a new car.
Customers table
customer - sunroof - mag_wheels - spoiler
--------------------------------------------------
John - true - true - false
Steve - false - true - false
Lucy - false - false - false
Options table
option - price
-----------------
sunroof - 100
mag_wheels - 150
spoiler - 75
Desired results
customer - cost
-----------------
John - 250
Steve - 150
Lucy - 0
or this would do, as I good easily multiply selected by price and then group by customer
customer - option - selected - price
------------------------------------------
John - sunroof - true - 100
John - mag_wheels - true - 150
John - spoiler - false - 75
Steve - sunroof - false - 100
Steve - mag_wheels - true - 150
Steve - spoiler - false - 75
Lucy - sunroof - false - 100
Lucy - mag_wheels - false - 150
Lucy - spoiler - false - 75
I've been puzzling over this for hours now and I can't even figure out where to start, a join seems out of the question as there are no common elements to match. I wonder if using UNION is the answer but I can't figure out how to combine row values with column headings.
If anyone could point me in the right direction I'd be ever so grateful, double points if you come up with a solution that dynamically picks up the different options so I could add more in the future without rewriting the query.
Many thanks in advance.
The reason I wanted to have all the options as a single row is I was hoping to use Access to make a form for picking the options and I couldn't figure out how a single form could create multiple rows.
This is a horrible data layout. You should have an association table, with one row per customer and option.
But, you can do it:
select c.customer, sum(o.cost) as cost
from customers c left outer join
options o
on (c.sunroof = true and o.option = 'sunroof' or
c.mag_wheels = true and o.option = 'mag_wheels' or
c.spoiler = true and o.option = 'spoiler'
)
group by c.customer;
EDIT:
You do not want all options in a single record. Instead, you need an association table:
create table customer_options (
customer_optionid unsigned auto_increment,
customer varchar(255) references customer(name),
option varchar(255) references option(option)
);
Actually you should really have integer primary keys for all the tables, and use them for the foreign key references. If you need data in the output in the question, then just write a query to return it in that format.
Looking at the table structure, even I think it will not be possible to write joins because as you mentioned, the table structure doesn't have a relation between them.
I am assume you have just started the project, so it's time you first re-visit your DB structure and correct it.
Ideally, you should have a customer table with a customer id.
Then you should have products table with product id.
One table which will have data on what products customers have purchased - something like customer_products. This will be a one to many relation. So customer 1 can have product 1,3 and 5. Which would means in customer_product there will be three entries.
And then when you want to do a sum total, you can first join the table customer, product based on customer_product and then do a sum of the price also to get the total amount for individual customer.
Bad design. You must a have a customers table like this:
custumer_id
customer_name
other fileds...
On the other hand you should have an accesories table, where you usually describe each item-
accesory_id
accesory_name
supplier_id
country_of_origin
other stuff
Also an accesory_price table, where prices are added due the fact that prices change.
accesory_id
price
active_price
date_price_added
An finally you should relate all in a customer_accesory table:
customer_id
accesory_id
By having this, you can join tables and select both customer basket size and customer preferences of accesories. Basket size, or the amount purchased by each customer can be summarized SUM, AVG, COUNT or you can pivot data using GROUP_CONCAT in order to generate high quality reports.

SQL: multiple groupings needed to track duplicates

I have a table, node_saved_data, setup like this:
set_id - node_id - node_value
The values will look something like
2 - 1 - some text
2 - 2 - more text
2 - 3 - a bit more text
2 - 4 - some more text
2 - 5 - even more text
I want to see if there are any duplicate node ids within each set. I tried
SELECT set_id, node_id, COUNT(node_id) c FROM node_saved_data GROUP BY node_id, set_id
but the results were clearly not what I wanted. Any advice? Let me know if you need more information.
I determined I only had to reverse the grouping order I was using. After that It gave me the results I was expecting
I think you're pretty close. Drop a HAVING clause at the end to check for those combinations with more than 1 entry.
select
set_id, node_id, count(1)
from
node_saved_data
group by
set_id,
node_id
having
count(1) > 1

MySQL Database Design for Prices / Specials

Below is an example of what I need to design in the database:
There will be an option for a price, and then a special if it has one, and then I was wondering how I could do this if I wanted one of the options to be "FREE".
See also there will be different currencies based on their country. Here is what I had in mind:
id - service_name - price - special_price - eco_friendly - free
1 - Rotate Tires - 9.00 - NULL - 1 - 1
2 - Service - 120.00- 100.00 - NULL - NULL
Would that work or is there a better way to do this? The eco-friendly will just display an icon in the HTML if it is set.
Thanks!
Set the special_price to 0 and let the presentation layer print FREE if the price is 0.
That way you can also do discount calculations and other things so that the price actually drops to 0 and then becomes "FREE" to the customer.