Data selected from three tables repeats itself - mysql

I have created three tables (cars,colors and brand) with mysql. I want to select data from the three tables but the data are being repeated.
Note: Please the car_ID in the colors and brands table references the car_ID column from cars table.
cars table
car_ID | type
1 | 300
2 | 200
colors table
id | color | car_ID
1 | red | 1
2 | blue | 1
3 | black| 2
4 | green| 2
brands
id | brand | car_ID
1 | BMW | 1
2 | cst | 1
3 | ash | 2
4 | golf | 2
SELECT
a.car_ID
b.color
c.brand
FROM
cars a
INNER JOIN
colors b
ON
a.car_ID=b.id
INNER JOIN
brands c
ON
a.car_ID=c.id
WHERE
a.Car_ID=1;
This repeats the needed data, this is what i receive
Car_ID | colors | brands
1 | red | BMW
1 | blue | cst
1 | red | BMW
1 | blue | cst
However, the data below is what i desire to receive
id | colors | brands
1 | red | BMW
1 | blue | cst
UPDATE
Sorry guys, I have updated my tables data and hope this time around it make sense.
Please what am I doing wrong in my query above. Thanks for helping.

(I typed this out.. then realised that I have no clue what you want to do... But I'll leave this out anyway)
Your tables aren't very well defined... here is my proposed table structure:
cars table
id | type_id | colour_id
1 | 1 | 1
2 | 2 | 4
Car type id
id | brand_id | name
1 | 1 | 300
2 | 1 | 200
Colours table
id | name
1 | Red
2 | Blue
3 | Black
4 | Green
Brands table:
id | name
1 | BMW
2 | cst
3 | ash
4 | golf
Query...
SELECT c.id as car_id, t.name as `type`, b.name as `brand`, co.name as `colour`
FROM cars c
INNER JOIN types t ON t.id = cars.type_id
INNER JOIN brands b ON b.id = t.brand_id
INNER JOIN colours co ON co.id = c.colour_id
It should return something like below
car_id | type | brand | colour
1 | 300 | BMW | Red
2 | 300 | BMW | Green

It's hard to guess from your question how everything works, but it seems like you might want ...
SELECT a.car_ID
b.color
c.brand
FROM cars a
INNER JOIN colors b ON a.car_ID=b.car_ID /* changed ON criterion */
INNER JOIN brands c ON a.car_ID=c.car_ID
WHERE a.Car_ID=1
I'm guessing that you use car_ID throughout to relate the tables to each other.

Related

MySQL - join multiple mapped tables and count records with different mapping conditions

It's the 3rd day I'm trying to write a MySQL query. Did lots of search, but it still doesn't work as expected. I'll try to simplify tables as much as possible
System has tkr_restaurants table:
restaurant_id | restaurant_name
1 | AA
2 | BB
3 | CC
Each restaurant has a division assigned (tkr_divisions table):
division_id | restaurant_id | division_name
1 | 1 | AA-1
2 | 1 | AA-2
3 | 2 | BB-1
Then there are meals in tkr_meals_to_restaurants_divisions table, where each meal can be assigned (mapped) to whole restaurant(s) and/or specific division(s). If meal is mapped to restaurant, all restaurant's divisions should see it. If meal is mapped to division(s), only specific division(s) should see it.
meal_id | mapped_restaurant_id | mapped_division_id
1 | 1 | NULL
2 | NULL | 1
3 | NULL | 2
I need to display a list of restaurants and number of meals mapped to it depending on user permissions.
Example 1: if user has permissions to access whole restaurant_id 1 and restaurant_3 (and no specific divisions), then list should be:
AA | 3
CC | 0
(because user can access meals mapped to restaurant 1 + all its division, and restaurant 3 + all its divisions (even if restaurant 3 has no divisions/meals mapped))
Example 2: if user has permissions to access only division_id 1, then list should be:
AA | 1
(because user can only access meals mapped to division 1).
The closest query I could get is:
Example 1:
SELECT *,
(SELECT COUNT(DISTINCT meal_id)
FROM
tkr_meals_to_restaurants_divisions
WHERE
tkr_meals_to_restaurants_divisions.mapped_restaurant_id=tkr_restaurants.restaurant_id
OR tkr_meals_to_restaurants_divisions.mapped_division_id=tkr_divisions.division_id)AS total_meals
FROM
tkr_restaurants
LEFT JOIN
tkr_divisions
ON tkr_restaurants.restaurant_id=tkr_divisions.restaurant_id
WHERE
tkr_restaurants.restaurant_id IN (1, 3)
OR tkr_restaurants.restaurant_id IN (
SELECT restaurant_id
FROM tkr_divisions
WHERE division_id IN (NULL)
)
GROUP BY
tkr_restaurants.restaurant_id
ORDER BY
tkr_restaurants.restaurant_name
However, result was:
AA | 2
CC | 0
I believe I'm greatly over-complicating this query, but all the simpler queries I wrote produced even more inaccurate results.
What about this query:
SELECT
FROM tkr_restaurants AS a
JOIN tkr_divisions AS b
ON a.restaurant_id = b.restaurant_id
LEFT OUTER JOIN tkr_meals_to_restaurants_divisions AS c
ON (c.mapped_restaurant_id = a.restaurant_id OR c.mapped_division_id = b.division_id)
As a Base four your further work. It combine all information into one table. If you add e.g. this:
WHERE a.restaurant_id IN (1, 3)
the result will be
| restaurant_id | restaurant_name | division_id | restaurant_id | division_name | meal_id | mapped_restaurant_id | mapped_division_id |
|---------------|-----------------|-------------|---------------|---------------|---------|----------------------|--------------------|
| 1 | AA | 1 | 1 | AA-1 | 1 | 1 | (null) |
| 1 | AA | 2 | 1 | AA-2 | 1 | 1 | (null) |
| 1 | AA | 1 | 1 | AA-1 | 2 | (null) | 1 |
| 1 | AA | 2 | 1 | AA-2 | 3 | (null) | 2 |
just count the distinct meal ids with COUNT(DISTINCT c.meal_id) and take the restaurant name to get AA: 3 for your example 2
I used a sqlfiddle: http://sqlfiddle.com/#!9/fa2b78/18/0
[EDIT]
Change JOIN tkr_divisions AS b to LEFT OUTER JOIN tkr_divisions AS b
Change SELECT * to SELECT a.restaurant_name, COUNT(DISTINCT c.meal_id)
Add a GROUP BY a.restaurant_name at the end.
Update the SQL Fiddle (new link)

MySQL: Joining two tables, but getting just the first value in second table

I have two tables that I am trying to join.
car_make Table:
id | name | color
---------------------------
12 | Tayota | red
13 | Ford | gray
15 | Tesla | red
17 | GM | blue
car_type table:
id | car_id | image_one | image_two | image_three
--------------------------------------------------------------------------
1 | 12 | tayota1.jpg | tayota2.jpg | tayota3.jpg
2 | 17 | gm1.jpg | gm2.jpg | gm3.jpg
3 | 12 | tayota3.jpg | tayota4.jpg | tayota5.jpg
4 | 13 | ford1.png | ford2.png | ford3.png
5 | 13 | ford4.png | ford5.png | ford6.png
I want to grab and display every row within car_make, and join the first image_one instance for each make.
For example, I would like it to output:
Row 1: Tayota, red, tayota1.jpg
Row 2: Ford, gray, ford1.jpg
Row 3: Tesla, red, NULL
Row 4: GM, blue, gm1.jpg
How would I structure this query?
Because you want the equivalent of a left join and only want one row, the easiest way might be a correlated subquery:
select cm.*,
(select ct.image_one
from car_type ct
where ct.car_id = cm.id
order by ct.id
limit 1
) as image_one
from car_make cm;
There are several ways you can do this. Here's one using a sub-query to ensure you're only selecting the 1st car type per car make
select * from car_make cm
left join car_type ct on ct.car_id = cm.id
and ct.id = (select min(id) from car_type ct2 where ct2.car_id = ct.car_id)

Count value from table column

first I have a table which is pivot looks like this
pivot_product_Id | productsxx_Id | category_Id | subcategory_Id | color_Id
---------------------------------------------------------------------------
1 | 1 | 1 | 1 | 1
2 | 1 | 1 | 1 | 2
3 | 3 | 1 | 1 | 3
4 | 4 | 1 | 2 | 4
5 | 4 | 1 | 2 | 5
6 | 2 | 2 | 4 | 6
7 | 5 | 2 | 5 | 7
and I have color table like this
color_Id | color | color2
------------------------------------------
1 | black | white
2 | blue | orange
3 | white | black
4 | purple | black
5 | black | green
6 | red | black
and my question is in category ID 1 or 2 ... how many black color exist ? Counting from both color and color2 columns
and I tryed something like this but not geting the result I want and need help to create right query.
if(isset($shoes_post_var) || isset($nightwear_post_var)|| isset($outwear_post_var)){
$query3 = "SELECT count(*)
FROM pivot
JOIN category ON
pivot.category_Id = category.category_Id
JOIN subcategory ON
pivot.subcategory_Id = subcategory.subcategory_Id
JOIN color ON
pivot.color_Id = color.color_Id
JOIN productsxx ON
pivot.productsxx_Id = productsxx.productsxx_Id
WHERE
color IN ('$black')
or
color2 IN ('$black')
AND
category IN ('$shoes_post_var','$nightwear_post_var','$outwear_post_var')
GROUP BY pivot.color_Id ASC ";
$query5 = mysql_query($query3)or die(mysql_errno());
$total = mysql_result($query5, 0);
echo ' '.'('.$total.')';}
A possible solution
SELECT COUNT(*) total
FROM pivot
WHERE category_id IN (1, 2)
AND color_id IN
(
SELECT color_id
FROM color
WHERE color = 'black'
OR color2 = 'black'
)
Here is SQLFiddle demo
You only described two tables and asked about a query based on these two tables. This is a matter of a simple join with a simple selection - and a count - something like this:
SELECT count(1)
FROM pivot
JOIN color ON (pivot.color_id=color.color_id AND 'black' in (color.color, color.color2))
WHERE pivot.category_id = 1
Feel free to change the where clause for other categories.
However your existing code joins 5 tables and uses some other selection criteria. You really do need to ask the right question. Don't try to ask one thing while implying another.

select query to calculate number of occurrence as well as total cost

I have one report page which displays summarized data of other report.I have used php and mysqli. Let me explain you in deep.
I have a web application of store, where you can add product details. Using these product details you can generate packaging list report of products. And based on the generated packaging list report I need to generate one other report which contains summarized data of the packaging list.
below are my tables:
product table:
id | name | desc_id | purity | style_no | type | duty
1 | ABC | 1 | 18 | TEST123 | R | 100
2 | XYZ | 2 | 14 | TEST456 | B | 80
3 | DEF | 1 | 14 | TEST122 | R | 80
4 | PQR | 1 | 18 | TEST124 | R | 120
5 | HJK | 3 | 18 | TEST134 | B | 300
Description table:
id | descrip
1 | Gold Diamond Ring
2 | Gold Diamond Pendant
3 | Gold Diamond Earring
packaging_master table
id | name
1 | pkg_1
2 | pkg_2
packging_details table
id | pkg_id | prod_id
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 1 | 4
5 | 1 | 5
I have used below query to generate the packaging list report for specific id, which works correctly.
SELECT id, (SELECT descrip FROM description WHERE id = desc_id ) AS descrip,
style_no, type , purity, duty FROM product WHERE id IN ( SELECT prod_id FROM packaging_list_details WHERE pkg_id =1 ) ORDER BY descrip ASC , purity ASC
which displays below result:
id | descrip | style_no | type | purity | duty
1 |Gold Diamond Ring | TEST123 | R | 18 | 100
4 |Gold Diamond Ring | TEST124 | R | 18 | 120
3 |Gold Diamond Ring | TEST122 | R | 14 | 80
2 |Gold Diamond Pendant| TEST456 | B | 14 | 80
5 |Gold Diamond Earring| TEST134 | B | 18 | 300
Now I want summarized data of above result using query.
Like:
id | descrip | purity | qty | duty
1 |Gold Diamond Ring | 18 | 2 | 220
2 |Gold Diamond Ring | 14 | 1 | 80
3 |Gold Diamond Pendant| 14 | 1 | 80
4 |Gold Diamond Earring| 18 | 1 | 300
How can I achieve this?
You need to use the GROUP_BY statement - See MySql docs for more info.
This will translate the query to such
SELECT d.descrip, p.purity, count(p.purity) as qty, sum(p.duty)
FROM product p
INNER JOIN Description d ON p.desc_id = d.id
LEFT OUTER JOIN packaging_details pg on pg.prod_id = p.id
GROUP BY d.descrip, p.purity
ORDER BY d.descrip desc, p.purity desc
You can also use the sub select methodology you were using, but I prefer using joins. INNER JOIN will link both tables so that all their records are returned. OUTER JOIN will return all rows from the tables on the LEFT of the statement and matches them to values from the tables on the RIGHT.
See a full SQL Fiddle sample.
NOTE: I am not sure where you are getting the values for Id in your sample - Are they simply row numbers?
I think you should rewrite your query using JOINs:
SELECT
P.id
,D.descrip
,P.style_no
,P.type
,P.purity
,P.duty
FROM
packaging_list_details PLD
JOIN
product P ON
(P.id = PLD.prod_id)
LEFT JOIN
description D on
(D.desc_id = P.id)
WHERE
(PLID.pkg_id = 1)
That should give you the same result you already have. To get the totals, you can write a new query, similar to the above:
SELECT
P.id
,D.descrip
,P.type
,P.purity
,COUNT(p.id) as total_products
,SUM(P.duty) as total_duty
FROM
packaging_list_details PLD
JOIN
product P ON
(P.id = PLD.prod_id)
LEFT JOIN
description D on
(D.desc_id = P.id)
WHERE
(PLID.pkg_id = 1)
GROUP BY
P.id
,D.descrip
,P.type
,P.purity
The second query gives you the totals you are looking for.

MySQL JOIN - Return NULL for duplicate results in left table

I believe this is a pretty simple thing, and I swear I've done it before but I can't remember how.
So let's say I have a one-to-many relationship. I want to JOIN the two tables, but not allow duplicates for the left table.
SQLFIDDLE
So based on the above SQLFiddle, my results would be:
categories.title | items.NAME | items.category_id
-----------------------------------------------------
red | apple | 1
red | car | 1
red | paper | 1
yellow | lego | 2
yellow | banana | 2
blue | pen | 3
I want it to be:
categories.title | items.NAME | items.category_id
-----------------------------------------------------
red | apple | 1
NULL | car | 1
NULL | paper | 1
yellow | lego | 2
NULL | banana | 2
blue | pen | 3
My reasoning is that this way, I can easily loop over the results without having to do any further processing with PHP.
You can replace the values with something like this:
select
case when rownum = 1 then title else null end title,
name,
category_id
from
(
SELECT c.title,
i.name,
i.category_id,
#row:=(case when #prev=title and #precat=category_id
then #row else 0 end) + 1 as rownum,
#prev:=title ptitle,
#precat:=category_id pcat
FROM items AS i
INNER JOIN categories AS c
ON c.id = i.category_id
order by i.category_id, c.title
) src
order by category_id, rownum
See SQL Fiddle with Demo
The result is:
| TITLE | NAME | CATEGORY_ID |
---------------------------------
| red | apple | 1 |
| (null) | car | 1 |
| (null) | paper | 1 |
| yellow | lego | 2 |
| (null) | banana | 2 |
| blue | pen | 3 |
It might be a long time ago when this was post. But I'll post my answer to the future readers. There is another process that is light and quick to understand.
You can make good use of variables. No subqueries are necessary.
SET #previous:="";
SELECT
IF(C.title=#previous, "", #previous:=C.title) AS Titles,
I.name, I.category_id
FROM items I
INNER JOIN categories AS C ON C.id = I.category_id
ORDER BY I.id, I.name
#previous is the variable that is being used.
SQL FIDDLE DEMO