MySQL order by index and then duplicates together - mysql

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 |

Related

MYSQL search multiple condition in one column

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

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

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.

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.