mySQL query not returning unique prices for each option - mysql

I am running the following mySQL query which is returning the incorrect price for each product option. (Each option has a different price for testing purposes).
How can I return the individual prices for each option?
The DB schema can be seen here:
http://www.webassist.com/tutorials/Free-eCommerce-MySQL-Database
SELECT ProductName AS productname, ProductCategoryID,
pov.OptionGroupName AS groupname,
povd.OptionName AS optionname,
pd.OptionPrice as price
FROM products p
LEFT JOIN productoptions pd ON (p.ProductID = pd.ProductID)
LEFT JOIN optiongroups pov ON (pd.OptionGroupID = pov.OptionGroupID)
LEFT JOIN options povd ON (pov.OptionGroupID = povd.OptionGroupID)
WHERE p.ProductID = 1
GROUP BY groupname, povd.OptionName
Currently getting this (note the prices):
+-------------+-------------------+-----------+------------+-------+
| ProductName | ProductCategoryID | GroupName | OptionName | Price |
+-------------+-------------------+-----------+------------+-------+
| Item1 | 1 | Color | Black | 2.00 |
| Item1 | 1 | Color | Red | 2.00 |
| Item1 | 1 | Color | Blue | 2.00 |
| Item1 | 1 | Size | Small | 5.00 |
| Item1 | 1 | Size | Medium | 5.00 |
+-------------+-------------------+-----------+------------+-------+
Should be like this (with unique prices):
+-------------+-------------------+-----------+------------+-------+
| ProductName | ProductCategoryID | GroupName | OptionName | Price |
+-------------+-------------------+-----------+------------+-------+
| Item1 | 1 | Color | Black | 2.00 |
| Item1 | 1 | Color | Red | 3.00 |
| Item1 | 1 | Color | Blue | 4.00 |
| Item1 | 1 | Size | Small | 5.00 |
| Item1 | 1 | Size | Medium | 6.00 |
+-------------+-------------------+-----------+------------+-------+
Here are data sets for all tables concerned (thanks for the guidance, Strawberry!).
Products Table
+-----------+-------------+-------------------+
| ProductID | ProductName | ProductCategoryID |
+-----------+-------------+-------------------+
| 1 | T-Shirt1 | 1 |
+-----------+-------------+-------------------+
OptionGroups Table
+---------------+-----------------+
| OptionGroupID | OptionGroupName |
+---------------+-----------------+
| 1 | color |
| 2 | size |
+---------------+-----------------+
ProductOptions Table
+-----------------+-----------+----------+-------------+---------------+
| ProductOptionID | ProductID | OptionID | OptionPrice | OptionGroupID |
+-----------------+-----------+----------+-------------+---------------+
| 1 | 1 | 1 | 2.00 | 1 (color) |
| 2 | 1 | 2 | 3.00 | 1 (color) |
| 3 | 1 | 3 | 4.00 | 1 (color) |
| 4 | 1 | 4 | 5.00 | 2 (size) |
| 5 | 1 | 5 | 6.00 | 2 (size) |
+-----------------+-----------+----------+-------------+---------------+
Options Table
+----------+---------------+------------+
| OptionID | OptionGroupID | OptionName |
+----------+---------------+------------+
| 1 | 1 | black |
| 2 | 1 | red |
| 3 | 1 | blue |
| 4 | 2 | Small |
| 5 | 2 | Small |
+----------+---------------+------------+

I took your query, scaisEdge, and made some changes to it. I removed the min/max stuff, changed the way the Left Join was done on ProductOptions, and changed the Where clause and Group By. Seems to be working correctly:
+-------------+-------------------+-----------+------------+-------+
| ProductName | ProductCategoryID | GroupName | OptionName | Price |
+-------------+-------------------+-----------+------------+-------+
| Item1 | 1 | Color | Black | 2.25 |
| Item1 | 1 | Color | Red | 3.25 |
| Item1 | 1 | Color | Blue | 4.25 |
| Item1 | 1 | Size | Small | 5.25 |
| Item1 | 1 | Size | Medium | 6.25 |
+-------------+-------------------+-----------+------------+-------+
The Query at this point:
SELECT ProductName AS productname, ProductCategoryID,
pov.OptionGroupName AS groupname,
povd.OptionName AS optionname,
pd.OptionPrice AS price,
povd.OptionID AS optionid
FROM products p
LEFT JOIN productoptions pd ON (pd.OptionID = optionid)
LEFT JOIN optiongroups pov ON (pd.OptionGroupID = pov.OptionGroupID)
LEFT JOIN options povd ON (pov.OptionGroupID = povd.OptionGroupID)
WHERE p.ProductID = 1 and povd.OptionID = pd.OptionID
GROUP BY povd.OptionID,
groupname, povd.OptionName
Thanks a lot for your help on this, scaisEdge.
And thanks to Strawberry for guiding me on how to format my questions on the site.
I truly believe that if a member 'down-votes' a question they should be required to explain why, so that we newbies can learn without simply being demoted and learning nothing from it.

Related

How to fetch product variant from MySQL

How to fetch product variant from table. How to apply MySQL query for this
products
+----+--------------+
| id | product_name |
+----+--------------+
| 1 | IPhone |
+----+--------------+
product_variants
+----+------------+-----------------+
| id | product_id | product_variant |
+----+------------+-----------------+
| 1 | 1 | COLORS |
| 2 | 1 | RAM |
| 3 | 1 | STORAGE |
+----+------------+-----------------+
product_variant_options
+----+------------+-----------------+
| id | variant_id | product_variant |
+----+------------+-----------------+
| 1 | 1 | BLUE |
| 2 | 1 | GOLD |
| 3 | 2 | 8GB |
| 4 | 2 | 12GB |
| 5 | 3 | 64GB |
| 6 | 3 | 128GB |
+----+------------+-----------------+
I want output like this
output
+----+------------+--------------+---------+------------+
| id | product_id | product_name | variant | options |
+----+------------+--------------+---------+------------+
| 1 | 1 | IPhone | COLOR | BLUE,GOLD |
| 2 | 1 | IPhone | RAM | 8GB,12GB |
| 3 | 1 | IPhone | STORAGE | 64GB,128GB |
+----+------------+--------------+---------+------------+
I don't have the DB data to try, but this should work
SELECT
products.id, product_variants.product_id, products.product_name,
product_variants.product_variant,
(SELECT GROUP_CONCAT(product_variant) FROM product_variant_options AS vo WHERE vo.variant_id = product_variants.id) AS options
FROM
products
LEFT JOIN product_variants ON products.id = product_variants.product_id
Just join the products and the product_variants table and GROUP_CONCAT the options
I can provide another solution without sub-query:
select
pv.id id,
p.id product_id,
product_name,
pv.product_variant,
group_concat(pvo.product_variant) variants
from products p
join product_variants pv on p.id = pv.product_id
join product_variant_options pvo on pvo.variant_id = pv.id
group by p.id, product_name, pv.id, pv.product_variant
;
Share SQL code
Result:
+====+============+==============+=================+============+
| id | product_id | product_name | product_variant | variants |
+====+============+==============+=================+============+
| 1 | 1 | IPhone | COLORS | BLUE,GOLD |
+----+------------+--------------+-----------------+------------+
| 2 | 1 | IPhone | RAM | 8GB,12GB |
+----+------------+--------------+-----------------+------------+
| 3 | 1 | IPhone | STORAGE | 64GB,128GB |
+----+------------+--------------+-----------------+------------+

MySQL - Sum Table 2 Column value(s) showing all Table 1 Descriptions

I have the following tables for Transactions and Categories respectively.
I am trying to write a query that will give me results shown in the Query table below.
I have tried the following
SELECT IFNULL(categories.Name,'Total') AS category,
IFNULL(SUM( transactions.Amount),0) AS amount,
categories.Color
FROM transactions,categories
WHERE categories.CatID = transactions.CatID
GROUP BY categories.Name WITH ROLLUP
This is however not giving me Category B. I would like my Category B to be shown with a Zero - 0 total as below. Please help..
Transactions
+-----------+------------+------------+--------+
| TransID | SaleDate | CatID | Amount |
+-----------+------------+------------+--------+
| 1 | 2012-02-10 | 1 | 10 |
| 2 | 2012-02-10 | 3 | 10 |
| 3 | 2012-02-10 | 3 | 20 |
| 4 | 2012-02-10 | 1 | 25 |
| 5 | 2012-02-10 | 1 | 35 |
| 6 | 2012-02-10 | 3 | 5 |
| 7 | 2012-02-10 | 3 | 5 |
+-----------+------------+------------+--------+
Categories
+------------+------+----------+
| CatID | Name | Color |
+------------+------+----------+
| 1 | A | Green |
| 2 | B | Red |
| 3 | C | Blue |
+------------+------+----------+
GETTING RESULT BELOW
+-----------+----------------+------------+
| Category | Amount | Color |
+-----------+----------------+------------+
| A | 70 | Green |
| B | 40 | Blue |
| Total | 110 | Blue |
+-----------+----------------+------------+
#
REQUIRED RESULT
+-----------+----------------+------------+
| Category | Amount | Color |
+-----------+----------------+------------+
| A | 70 | Green |
| B | 0 | Red |
| C | 40 | Blue |
| Total | 110 | Pink |
+-----------+----------------+------------+
You are looking for a left join with rollup:
select coalesce(c.category, 'total') as category,
coalesce(sum(t.amount), 0) as amount,
coalesce(c.color, 'pink') as color -- this is weird
from categories c left join
transactions t
on c.catid = t.catid
group by c.category with rollup;

MYSQL Union Operation with Gross, Cut & Net Amounts

I need to print Gross allocation, Cut Allocation & Net Allocation issued for various offices under relevant votes. I used the following tables.
1) Total issues (Gross Allocation) are in the Table, Named "issues_tot"
+---------+------+------------+
| v_code | oid | amount |
+---------+------+------------+
| 1 | 2 | 200,000.00 |
| 1 | 3 | 80,000.00 |
| 2 | 1 | 40,000.00 |
| 3 | 2 | 150,000.00 |
+---------+------+------------+
2) Cut amounts (Cut Allocation) are in the Table, Named "cp_tot"
+--------+-----+-----------+
| v_code | oid | amount |
+--------+-----+-----------+
| 1 | 2 | 68,000.00 |
| 1 | 3 | 50,000.00 |
| 3 | 2 | 75,000.00 |
+--------+-----+-----------+
3) Table, Named "vote"
+--------+-------------------------+
| v_code | vote |
+--------+-------------------------+
| 1 | 001-2-6-3-2502 |
| 2 | 001-1-4-21-2202 |
| 3 | 101-1-2-0-1405 |
+--------+-------------------------+
4) Table, Named "office"
+-----+----------------------+
| oid | office |
+-----+----------------------+
| 1 | Weeraketiya |
| 2 | Tissamaharama |
| 3 | District Sec |
+-----+----------------------+
And desired output as follows:
+--------+------------+-----------+------------+
| v_code | Gross | Cut | Net |
+--------+------------+-----------+------------+
| 1 | 200,000.00 | 68,000.00 | 132,000.00 |
| 1 | 80,000.00 | 50,000.00 | 30,000.00 |
| 2 | 40,000.00 | 0.00 | 40,000.00 |
| 3 | 150,000.00 | 75,000.00 | 75,000.00 |
+--------+------------+-----------+------------+
02) I used the following script to generate that output
select `vote`.`vote` AS `vote`,`office`.`office` AS `office`,
`issues_tot`.`amount` AS `Gross`,
coalesce(`cp_tot`.`amount`,0) AS `Cut`,
(`issues_tot`.`amount` - coalesce(`cp_tot`.`amount`,0)) AS `Net`
from (((`vote` join `issues_tot` on((`vote`.`v_code` = `issues_tot`.`v_code`))) join
`office` on((`office`.`oid` = `issues_tot`.`oid`))) left join
`cp_tot` on((`issues_tot`.`v_code` = `cp_tot`.`v_code`)))
But it generates the following output with repeated records:
+------------+----------------+--------------+-------------+--------------+
| Vote | Office | Gross | Cut | Net |
+---------------+-------------+--------------+-------------+--------------+
| 001-2-6-3-2502| Tissamaharama | 200,000.00 | 68,000.00 |132,000.00 |
| 001-2-6-3-2502| Tissamaharama | 200,000.00 | 50,000.00 | 150,000.00 |
| 001-2-6-3-2502| District Sec | 80,000.00 | 68,000.00 | 12,000.00 |
| 001-2-6-3-2502| District Sec | 80,000.00 | 50,000.00 | 30,000.00 |
| 001-1-4-21-2202| Weeraketiya | 40,000.00 | - | 40,000.00 |
| 101-1-2-0-1405 | Tissamaharama | 150,000.00 | 75,000.00 | 75,000.00 |
+------------+-----------------+--------------+-------------+--------------+
I can not understand what was going wrong. Can anyone help me?
Firstly, the following query will get what you want:
select
v.vote,
o.office,
it.amount as Gross,
coalesce(ct.amount , 0) as Cut,
it.amount - coalesce(ct.amount, 0) as Net
from issues_tot it
left join cp_tot ct
on it.v_code = ct.v_code
and it.oid = ct.oid
left join vote v
on it.v_code = v.v_code
left join office o
on it.oid = o.oid
order by it.v_code
and SQLFiddle Demo Here, the only issue is that you forget to match oid between issues_tot and cp_tot.
If there is no oid criteria, the match will do like following:
# issues_tot # cp_tot
| v_code | oid | amount | | v_code | oid | amount |
+---------+------+------------+ +--------+-----+-----------+
| 1 | 2 | 200,000.00 | -> | 1 | 2 | 68,000.00 |
| 1 | 3 | 50,000.00 |
| 1 | 3 | 80,000.00 | -> | 1 | 2 | 68,000.00 |
| 1 | 3 | 50,000.00 |
| 2 | 1 | 40,000.00 | -> no record match
| 3 | 2 | 150,000.00 | -> | 3 | 2 | 75,000.00 |
so 6 records by your query is it.

MySql - LEFT JOIN on preference but have no duplicates

So I have to join a table onto a value from another table however it should only return 1 value from the joined table.
The relationships of these tables are very vague - as is the nature of the data I am dealing with. The name in the ''Cookies'' table could be either one of CookieAttr1, CookieAttr2 or CookieAttr3.
Cookies
|-----------------------------|
| CookieName | CookieValue |
|-------------+---------------|
| Choc-Chip | 1200 |
| Dough | 500 |
|-----------------------------|
CookieColor
|-----------------------------------------------------------------|
| Id | CookieAttr1 | CookieAttr2 | CookieAttr3 | Color |
|-----+---------------+---------------+---------------+-----------|
| 1 | | Choc-Chip | Dough | Red |
| 2 | | Choc-Chip | Crumbs | Orange |
| 3 | | Sultanas | Dough | Red |
| 4 | | Choc-Chip | Dough | Blue |
| 5 | Dough | | Rounded | Purple |
| 6 | Dough | Big | Rounded | Green |
| 7 | Rounded | | Rounded | Pink |
|-----------------------------------------------------------------|
So far the table is joined on preference - where if CookieAttr1 is null it will then join on CookieAttr2 and then CookieAttr3 (which will always have a value)
SELECT
CookieName,
CookieValue,
Color
FROM Cookies
LEFT OUTER JOIN (
SELECT
Color,
CookieAttr1,
CookieAttr2,
CookieAttr3
FROM CookieColor
GROUP BY CookieAttr3
) CookieColor
ON COALESCE(CookieAttr1, CookieAttr2, CookieAttr3) = CookieName
The problem occurs that the table can return duplicates as grouping by CookieAttr3 might have multple same CookieAttr2 values on which it is joining on.
CookieColor (GROUPED BY `CookieAttr3`)
|-----------------------------------------------------------------|
| Id | CookieAttr1 | CookieAttr2 | CookieAttr3 | Color |
|-----+---------------+---------------+---------------+-----------|
| 1 | | Choc-Chip | Dough | Red |
| 2 | | Choc-Chip | Crumbs | Orange |
| 5 | Dough | | Rounded | Purple |
|-----------------------------------------------------------------|
==========> result of query
|-----------------------------------------|
| CookieName | CookieValue | Color |
|-------------+---------------+-----------|
| Choc-Chip | 1200 | Red |
| Choc-Chip | 1200 | Orange |
| Dough | 500 | Purple |
|-----------------------------------------|
==========> Preferred Result
|-----------------------------------------|
| CookieName | CookieValue | Color |
|-------------+---------------+-----------|
| Choc-Chip | 1200 | Red |
| Dough | 500 | Purple |
|-----------------------------------------|
How can I only get one value for 'Choc-Chip'?
You can always use a COALESCE in one subquery, but your group by isnt clear
SQL Fiddle Demo
SELECT CookieAttr, Color, CookieValue
FROM
(
SELECT `Id`,
COALESCE(CookieAttr1, CookieAttr2, CookieAttr3) CookieAttr,
`Color`
FROM CookieColor
) C
JOIN Cookies
ON C.CookieAttr = Cookies.CookieName
OUTPUT
But dont know what group by you want from this.
| CookieAttr | Color | CookieValue |
|------------|--------|-------------|
| Choc-Chip | Orange | 1200 |
| Choc-Chip | Blue | 1200 |
| Choc-Chip | Red | 1200 |
| Dough | Purple | 500 |
| Dough | Green | 500 |
If you add
GROUP BY CookieAttr;
But color will be random.
| CookieAttr | Color | CookieValue |
|------------|--------|-------------|
| Choc-Chip | Orange | 1200 |
| Dough | Purple | 500 |

How to get data from three tables MySQL?

I have three tables: names of products, names of parameters and values of parameters for some of products:
products
+-------+-------------+
| id | name |
+-------+-------------+
| 1 | A100 |
+-------+-------------+
| 2 | B250 |
+-------+-------------+
params
+-------+-------------+
| id | name |
+-------+-------------+
| 1 | width |
+-------+-------------+
| 2 | color |
+-------+-------------+
paramsofproducts
+-------+-----------+-----------+-----------+
| id | product | param | value |
+-------+-----------+-----------+-----------+
| 1 | 1 | 1 | 120 |
+-------+-----------+-----------+-----------+
| 2 | 1 | 2 | white |
+-------+-----------+-----------+-----------+
| 3 | 2 | 1 | 275 |
+-------+-----------+-----------+-----------+
| 4 | 2 | 2 | black |
+-------+-----------+-----------+-----------+
And how to get by one query this table (all products + parameters as columns)? I can't do it with JOIN.
+-------+----------+-----------+-----------+
| id | name | width | color |
+-------+----------+-----------+-----------+
| 1 | A100 | 120 | white |
+-------+----------+-----------+-----------+
| 2 | B250 | 275 | black |
+-------+----------+-----------+-----------+
I can't present the result you want, but maybe is some JSON in your result a possible workaround:
SELECT products.id, products.name, CONCAT('[{',GROUP_CONCAT('"',REPLACE(params.name, '"', '\\"'),'":"', REPLACE(paramsofproducts.value, '"', '\\"'),'"'),'}]') as params
FROM paramsofproducts
LEFT JOIN products ON products.id = paramsofproducts.product
LEFT JOIN params ON params.id = paramsofproducts.param
GROUP BY products.name
Result:
id | name | params
1 | A100 | [{"width":"120","color":"white"}]
2 | B250 | [{"width":"275","color":"black"}]
edit: escaping "