Count value from table column - mysql

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.

Related

mysql linked tables, return null if not present in connecting table

I have 2 tables that have a many-to-many relation, using a 3rd table.
Table 1 colors:
____________
id | color |
____________
1 | red |
2 | blue |
3 | yellow |
4 | orange |
5 | green |
table 2 content: (Table content is not really relevant for the query, I add it for completeness.)
id | itemname
1 | item1
2 | item2
3 | item3
...
table 3 is the connecting table colors_content
id | content_id | color_id
1 | 1 | 1
2 | 1 | 2
3 | 1 | 5
4 | 2 | 1
5 | 3 | 1
6 | 4 | 4
I want to return all colors + a way to figure out which ones are already linked to the content_id I am querying, so as an example, so for item.id=1 the result should be:
colors.id | colors.color | colors_content.content_id
1 | red | 1 (this can be anything, like a boolean)
2 | blue | 1
3 | yellow | null
4 | orange | null
5 | green | 1
again: it is a many-to-many relation, I need to output exactly 1 of each color, with a way to know if the queries item is already linked to it.
I have tried joining in different ways but I can not seem to find the correct syntax that includes the null values for unlinked colors.
SELECT c.* FROM `colors` c left join colors_content cc on cc.color_id=c.id where cc.content_id=1
only returns the 3 linked colors for item 1, not the 2 others.
edit:
This quite convoluted query seems to do the trick (although I am unclear why the group statement will not randomly choose between the queried id and the 0 value), but I must be missing a more obvious solution:
select * from ( SELECT c.id , c.color, cc.content_id as present FROM colors c JOIN colors_content cc ON c.id=cc.color_id WHERE cc.content_id=7 UNION select id , color, 0 as present from colors) as resulttable group by color
Move the check for the content_id in the ON clause and then check if the color_id of colors_content is NULL.
SELECT c.id,
c.color,
cc.colorid IS NULL exists_for_content_id
FROM colors c
LEFT JOIN colors_content cc
ON cc.color_id = c.id
AND cc.content_id = 1;
(This assumes that (colors.id), (content.id) and (colors_content.content_id, colors_content.color_id) are not nullable and unique.)

group by a random not null entry

I have a table usercolor like this:
id | idUser | color
-----------------------
1 | 1 | red
2 | 1 | blue
3 | 2 | green
4 | 2 | blue
5 | 3 | null
6 | 3 | blue
7 | 4 | null
I would like to have for each idUser one random fitting color which is not null whenever possible. Like this:
idUser | color
---------------
1 | blue
2 | green
3 | blue
4 | null
I thought I could achieve it by
SELECT idUser, color FROM usercolor GROUP BY idUser
However, with this SQL it might happen that idUser 3 is mapped to null although there exists the color blue for that idUser. How could I prevent that?
If you want one random color per user, then a correlated subquery comes to mind:
select idUser,
(select uc.color
from usercolor uc
where uc.idUser = u.idUser and uc.color is not null
order by rand()
limit 1
) as color
from (select distinct idUser from usercolor) u -- you can use `users` here instead

select records from Foreign Key table where one item matches multiple condition

I have two tables like below. how can I select records that have values 'orange' and 'blue' in a same time.
+----+----------+
| ID |SECOND_ID |
+----+----------+
| 10 | 1 |
| 20 | 2 |
| 30 | 3 |
+----+----------+
+-----------+----------+
| SECOND_ID | COLOR |
+-----------+----------+
| 1 | blue |
| 1 | orange |
| 2 | blue |
| 2 | orange |
| 3 | orange |
+-----------+----------+
EDIT
ok I admit that I didn't explain the problem well. first let's call the tables items for first table and items_color for second as Alex did.
these tables have one-to-many relationship where the SECOND_ID have more than one value each time. Now I want select rows that have blue and orange in a same time and It should be the row with ID = 1 and 2.
thanks for your time.
http://sqlfiddle.com/#!9/05254/1
SELECT *,
SUM(IF(items_colors.color='blue',1,0)) as blue,
SUM(IF(items_colors.color='orange',1,0)) as orange
FROM items
LEFT JOIN items_colors
ON items.second_id = items_colors.second_id
GROUP BY items.id
HAVING blue>0 and orange>0
There's many ways, simpliest one will be with subqueries:
SELECT'second_id' FROM 'table' WHERE 'color' = 'blue' AND 'second_id' =
(SELECT 'second_id' FROM 'table' WHERE 'color' = 'orange')
But I think this is not the most optimized way
Also, you can try with an INNER JOIN (it will work like an intersection)
SELECT * FROM items_colors as A INNER JOIN items_colors AS B ON
A.SECOND_ID = B.SECOND_ID AND A.color = 'blue' AND B.color = 'orange'

Data selected from three tables repeats itself

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.

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