MYSQL search multiple condition in one column - mysql

table1
-------------------------------
| id | color | shape |
|------------------------------
| 1 | green | triangle |
| 2 | green | square |
| 3 | blue | rectangle |
| 4 | white | sphere |
| 5 | yellow | triangle |
-------------------------------
I want to get a result where row has multiple condition focusing in one column.
Here is my code.
SELECT * FROM table1 WHERE shape = 'triangle' and shape = 'square';
However, result should have the same value in column color.
Is it possible to have a result as below?
-------------------------------
| id | color | shape |
|------------------------------
| 1 | green | triangle |
| 2 | green | square |
-------------------------------

One option uses not exists:
select t.*
from mytable t
where
shape in ('triangle', 'square')
and exists (
select 1
from mytable t1
where
t1.shape in ('triangle, 'square')
and t1.color = t.color
and t1.shape <> t.shape
)
If you are running MySQL 8.0, you can also use window functions. Assuming that there are no duplicates in (color, shape) tuples:
select id, color, shape
from (
select t.*, count(*) over(partition by color) cnt
from mytable t
where shape in ('triangle', 'square')
) t
where cnt > 1

Related

MySQL order by index and then duplicates together

I want to have the rows sorted by ID and then have the duplicates appear sequentially.
Example:
id color
1 red
2 green
3 yellow
4 green
5 green
6 red
Expected:
id color
1 red
6 red
2 green
4 green
5 green
3 yellow
If you are on MySql 8.0+ you can use MIN() window function:
select t.id, t.color
from (
select *,
min(id) over (partition by color) minid
from tablename
) t
order by t.minid, id
For previous versions:
select t.* from tablename t
order by (select min(id) from tablename where color = t.color), id;
See the demo.
Results:
| id | color |
| --- | ------ |
| 1 | red |
| 6 | red |
| 2 | green |
| 4 | green |
| 5 | green |
| 3 | yellow |

mysql get total values and total number from where clause

I'm trying to write a mysql query which will return the total number of values from a column and also the total number of values based on a where clause from the same column.
I have a table like this:
+------------------------+-------+
| color | code |
+------------------------+-------+
| red | 200 |
| red | 202 |
| blue | 105 |
| yellow | 136 |
| green | 561 |
| red | 198 |
| blue | 414 |
| green | 11 |
| yellow | 600 |
| green | 155 |
| red | 865 |
| blue | 601 |
| green | 311 |
+------------------------+-------+
If I run this query:
select
color,
count(*) as count
from colors
where code > 0 &&
code <= 500
group by color
order by count(*) desc;
I get this result which is great because it's almost what I want:
+------------------------+-------+
| color | count |
+------------------------+-------+
| red | 3 |
| green | 3 |
| blue | 2 |
| yellow | 1 |
+------------------------+-------+
What I also need returned is the total number of values in the column, so the result table would look like this.
+------------------------+--------------+-------+
| color | total | count |
+------------------------+--------------+-------+
| red | 4 | 3 |
| green | 4 | 3 |
| blue | 3 | 2 |
| yellow | 2 | 1 |
+------------------------+--------------+-------+
So the total is the number of each value in the color column and count is the total amount which matches the where clause.
Thanks :)
Here is the link to SQLFiddle.
http://sqlfiddle.com/#!9/777f93/2
You need to use conditional aggregation to handle the counts and let the engine handle the total.
SELECT color
, count(*) as Total
, sum(case when code > 0 and code <= 500 then 1 else 0 end) as cnt
FROM colors
GROUP BY color
ORDER BY cnt desc;
You can use conditional aggregation:
select color,
count(*) as Total,
sum(code > 0 and code <= 500) as count_0_to_500
from colors
group by color
order by count_0_to_500 desc
It uses the fact that true evaluates to 1 and false evaluates to 0 in MySQL.
It's basically what xQbert answered just without a case expression.
You can JOIN your query with another query, e.g.:
select color, count(*) as count , a.total
from colors JOIN (
SELECT color, count(*) as `total` FROM colors GROUP BY color
) a ON colors.code = a.color
where code > 0 && code <= 500
group by color
order by count(*) desc;
You case use a case when statement to count only those items that meet your criteria. Like this:
Select
color
, count(*) as total
, SUM(CASE WHEN code > 0 && code <= 500 THEN 1 ELSE 0 END ) as Count
group by color order by count(*) desc;
You can do it using join query and table alias
select t1.color,t1.total,t2.count
FROM
(select color, count(*) as total from colors group by color) t1,
(select color, count(*) as `count` from colors where `code` > 0 && `code` <= 500 group by color) t2
WHERE
t1.color=t2.color order by `count` desc;
Here is the link to SQLFiddle.
http://sqlfiddle.com/#!9/777f93/2

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

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.

Mysql: Swap data for different rows

Suppose a table fruits that looks like this:
------------------------------------------
| id | name | color | calories |
------------------------------------------
| 1 | apple | red | 20 |
| 2 | orange | orange | 10 |
| 3 | grapes | green | 5 |
| 4 | bananas | yellow | 15 |
| 5 | plum | purple | 25 |
------------------------------------------
How can I swap the values of a row, with another, leaving the id number intact?
Example:
SWAP ROW WITH ID "5" WITH ROW WITH ID "2"
Result:
------------------------------------------
| id | name | color | calories |
------------------------------------------
| 1 | apple | red | 20 |
| 2 | plum | purple | 25 |
| 3 | grapes | green | 5 |
| 4 | bananas | yellow | 15 |
| 5 | orange | orange | 10 |
------------------------------------------
Note that all the values are intact except for the id.
I need to do this with a really large list of values, so I need a one-liner, or at most, something that doesn't require the creation of temporary tables, and things like that.
Note: id is unique
Thank you
You could use a join inequality to line up the rows you want to swap:
update fruit a
inner join fruit b on a.id <> b.id
set a.color = b.color,
a.name = b.name,
a.calories = b.calories
where a.id in (2,5) and b.id in (2,5)
http://sqlfiddle.com/#!18/27318a/5
Since ID is unique, it is difficult to just swap the IDs, it's easier to swap the column contents. A query like this might be what you need:
UPDATE
yourtable t1 INNER JOIN yourtable t2
ON (t1.id, t2.id) IN ((1,5),(5,1))
SET
t1.color = t2.color,
t1.name = t2.name,
t1.calories = t2.calories
Please see fiddle here.
Here's a way to store values temporarily without using a temp table or a dummy row in your fruit table:
SELECT name, color, calories FROM fruit WHERE id = 2 INTO #name, #color, #calories;
UPDATE fruit AS f1, fruit AS f2
SET
f1.name = f2.name, f2.name = #name,
f1.color = f2.color, f2.color = #color,
f1.calories = f2.calories, f2.calories = #calories
WHERE (f1.id, f2.id) = (2, 5);
Here's another solution that uses a dummy id value:
UPDATE fruit SET id = 0 WHERE id = 5;
UPDATE fruit SET id = 5 WHERE id = 2;
UPDATE fruit SET id = 2 WHERE id = 0;
If your operations are based on ID, and you want to swap entire rows, a fancy way of swapping UNIQUE IDs is to start numbering them at 1, and use 0 as a temporary value.
Another way of performing this is using an unsigned column, and using a designated value (ie.: -1) for temporary. I wouldn't really recommend the latter, as we are effectively wasting space with this method. See http://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html for more details.