I have the following mysql table:
+----+-----+-----+--------+
| id | sid | tid | val |
+----+-----+-----+--------+
| 1 | 1 | 1 | square |
| 2 | 1 | 2 | big |
| 3 | 1 | 3 | red |
| 4 | 2 | 1 | circle |
| 5 | 2 | 2 | small |
| 6 | 2 | 3 | yellow |
+----+-----+-----+--------+
And I would need a query to get the following results:
+-----+--------+-------+--------+
| sid | figure | size | colour |
+-----+--------+-------+--------+
| 1 | square | big | red |
| 2 | circle | small | yellow |
+-----+--------+-------+--------+
Any ideas?
Thanks.
You didn't provide any details about how you determine the new column names but based on your data I am guessing that it is based on the values in the tid column. You can use an aggregate function with a case expression to get the result:
select
sid,
max(case when tid = 1 then val end) figure,
max(case when tid = 2 then val end) size,
max(case when tid = 3 then val end) color
from yourtable
group by sid;
See SQL Fiddle with Demo
Related
I am having trouble with an SQL query. I have two tables.
My first table:
+------------+-------------+---------------+
| id_mission | Some column | Other column |
+------------+-------------+---------------+
| 1 | ... | ... |
| 2 | ... | ... |
+------------+-------------+---------------+
My second table:
+------------+-------------+---------+
| id_mission | id_category | points |
+------------+-------------+---------+
| 1 | 1 | 3 |
| 1 | 2 | 4 |
| 1 | 3 | 4 |
| 1 | 4 | 8 |
| 2 | 1 | -4 |
| 2 | 2 | 3 |
| 2 | 3 | 1 |
| 2 | 4 | -7 |
+------------+-------------+---------+
And I would like to have this kind of result with my SELECT request
+------------+-------------+--------------+---------------+----------------+
| id_mission | Some column | Other column | id_category 1 | id_category X |
+------------+-------------+--------------+---------------+----------------+
| 1 | ... | ... | ... | ... |
| 2 | ... | ... | ... | ... |
+------------+-------------+--------------+---------------+----------------+
I have tried this with the first two column but it doesn't work, I also tried GROUP_CONCAT, it works but it's not the result I want.
SELECT m.id_mission ,mc.id_category 1,mc1.id_category 2
from mission m
left join mission_category mc on m.id_mission = mc.id_mission
left join mission_category mc1 on m.id_mission = mc1.id_mission
Can someone help me?
You can use conditional aggregation. Assuming that you want to pivot the points value per category:
select
t1.*,
max(case when t2.id_category = 1 then points end) category_1,
max(case when t2.id_category = 2 then points end) category_2,
max(case when t2.id_category = 3 then points end) category_3
from t1
inner join t2 on t2.id_mission = t1.id_mission
group by t1.id_mission
This assumes that id_mission is the primary key of t1 (else, you need to enumerate the columns you want in both the select and group by clauses).
I'm stuck and I can't figure it out, so I would appreciate any help.
At this point i have table journal which consists of columns:
id | name | type(int) | classification | data | journalUser | start_date(default NULL)
1 | John | 1 | 2 | data123 | 1 | 10-11-2019
2 | Peter | 2 | 2 | data123 | 1 | 10-11-2019
3 | Ash | 2 | 2 | data123 | NULL | NULL
4 | BUBU | 2 | 2 | data123 | 3 | 10-11-2019
I want to make query where I select all, but with exceptions, for example: SELECT * from journal, but if column type = 2, than select this row too if journalUser = 1 AND second check if column type = 2 and start_date IS NULL, than select this row too.
As the result, from table above, from query I wan to get result
id | name | type(int) | classification | data | journalUser | start_date(default NULL)
1 | John | 1 | 2 | data123 | 1 | 10-11-2019
2 | Peter | 2 | 2 | data123 | 1 | 10-11-2019
3 | Ash | 2 | 2 | data123 | NULL | NULL
That's a specific case when the type is 2.
To get the rows with type = 2 along with either (considering the expected output) journalUser = 1 or start_date = null, this can be written this way :
type = 2 AND (journalUser = 1 OR start_date IS NULL)
To make sure you have others type too, you can add an OR condition such as :
OR type <> 2.
This will give this query :
SELECT *
FROM journal
WHERE (type = 2 AND (journalUser = 1 OR start_date IS NULL))
OR type <> 2
Here is a table structure example:
// tablename
+----+------+---------+
| id | numb | color |
+----+------+---------+
| 1 | 4 | green |
| 2 | 4 | yellow |
| 3 | 3 | red |
+----+------+---------+
Here is a query example:
SELECT id, numb, color FROM tablename ORDER BY numb asc
The result will be:
+----+------+---------+
| id | numb | color |
+----+------+---------+
| 3 | 3 | red |
| 1 | 4 | green |
| 2 | 4 | yellow |
+----+------+---------+
Now, my focus is on the order of these rows:
| 3 | 4 | green |
| 2 | 4 | yellow |
Because their numb values are equal, Now I want to know, for several executing that query, they will be constant? (Is order guaranteed for the identical values?) Or there isn't any guarantee and I should use another column name in the query like this ORDER BY numb, id asc ?
Short answer: No, there is no guarantee. (as #Strawberry wrote under the question)
Full answer: You can add a new column named sort_identical, And fill it whatever you like. And then use this:
... ORDER BY numb, sort_identical asc
(Also you can use id instead of creating a new column - But if you need to sort it differently than id, then create a new column)
+----+------+---------+----------------+
| id | numb | color | sort_identical |
+----+------+---------+----------------+
| 3 | 3 | red | 1 |
| 1 | 4 | green | 2 |
| 2 | 4 | yellow | 3 |
+----+------+---------+----------------+
Actually my question is almost the same with MySQL: Select multiple rows containing values from one column, I want to find the car_id of the cars that have MAKE='FORD' AND COLOR='SILVER', so in this case here it will returns car_id 1 and 2.
PS: There could be multiple criteria at once, like I can search by MAKE + CARLINE + COLOR, MAKE + CARLINE, and etc.
table_cars
+----+--------+----------+-----------+
| id | car_id | name | value |
+----+--------+----------+-----------+
| 1 | 1 | MAKE | FORD |
| 2 | 1 | CARLINE | FIESTA |
| 3 | 1 | COLOR | SILVER |
| 4 | 1 | TOPSPEED | 210KM/H |
| 5 | 2 | MAKE | FORD |
| 6 | 2 | CARLINE | FOCUS |
| 7 | 2 | COLOR | SILVER |
| 8 | 2 | TOPSPEED | 200KM/H |
| 9 | 3 | MAKE | HOLDEN |
| 10 | 3 | CARLINE | ASTRA |
| 11 | 3 | COLOR | WHITE |
| 12 | 3 | TOPSPEED | 212KM/H |
+----+--------+----------+-----------+
Thank you!
select car_id
from your_table
group by car_id
having sum(name = 'MAKE' and value = 'FORD') > 0
and sum(name = 'COLOR' and value = 'SILVER') > 0
Try with self join as below:
SELECT distinct car_id
FROM mytable mt1 INNER JOIN mytable mt2
ON mt1.car_id = mt2.car_id
WHERE mt1.name = 'MAKE'
AND mt1.value = 'FORD'
AND mt2.name = 'COLOR'
AND mt2.value = 'SILVER'
I've the following table:
| id | Name | Date of Birth | Date of Death | Result |
| 1 | John | 3546565 | 3548987 | |
| 2 | Mary | 5233654 | 5265458 | |
| 3 | Lewis| 6546876 | 6548752 | |
| 4 | Mark | 6546546 | 6767767 | |
| 5 | Steve| 6546877 | 6548798 | |
And I need to do this for the whole table:
Result = 1, if( current_row(Date of Birth) - row_above_current_row(Date of Death))>X else 0
To make things easier, I guess, I created the same table above but with 2 extra id fields: id_minus_one and id_plus_one
Like this:
| id | id_minus_one | id_plus_one |Name | Date_of_Birth | Date_of_Death | Result |
| 1 | 0 | 2 |John | 3546565 | 3548987 | |
| 2 | 1 | 3 |Mary | 5233654 | 5265458 | |
| 3 | 2 | 4 |Lewis| 6546876 | 6548752 | |
| 4 | 3 | 5 |Mark | 6546546 | 6767767 | |
| 5 | 4 | 6 |Steve| 6546877 | 6548798 | |
So my approach would be something like (in pseudo code):
for id=1, ignore result. (Because there is no row above)
for id=2, Result = 1 if( (Where id=2).Date_of_Birth - (where id_minus_one=id-1).Date_of_Death )>X else 0
for id=3, Result = 1 if( (Where id=3).Date_of_Birth - (where id_minus_one=id-1).Date_of_Death)>X else 0
and so on for the whole table...
Just ignore id_plus_one if there is no need for it, I'll use it later for the same thing. So, if I manage to do this for id_minus_one I'll manage for id_plus_one as they are the same algorithm.
My question is how to pass that pseudo code into SQL code, I can't find a way to relate both ids in just one select.
Thank you!
As you describe this, it is just a self join with some logic on the select:
select t.*,
((t.date_of_birth - tprev.date_of_death) > x) as flag
from t left outer join
t tprev
on t.id_minus_one = tprev.id