I have a table where the data of measured temperature and humidity is stored. Records with temperature have the field meas_kind set to "T", and for humidity it is set to "H".
mysql> describe meteo;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| meas_time | timestamp | YES | | NULL | |
| room | varchar(10) | NO | | NULL | |
| meas_kind | char(1) | NO | | NULL | |
| value | double | NO | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
mysql> select * from meteo;
+----+---------------------+------+-----------+-------+
| id | meas_time | room | meas_kind | value |
+----+---------------------+------+-----------+-------+
| 35 | 2017-05-24 16:51:47 | 123 | T | 22.61 |
| 36 | 2017-05-24 16:51:47 | 123 | H | 36.93 |
| 37 | 2017-05-24 16:51:51 | 123 | T | 22.61 |
| 38 | 2017-05-24 16:51:51 | 123 | H | 36.94 |
| 39 | 2017-05-24 16:51:56 | 123 | T | 22.61 |
| 40 | 2017-05-24 16:51:56 | 123 | H | 36.94 |
+----+---------------------+------+-----------+-------+
Temperature and humidity are measured in the same time, so I want this table to be like this:
+---------------------+------+-------+-------+
| meas_time | room | Temp | Humid |
+---------------------+------+-------+-------+
| 2017-05-24 16:51:47 | 123 | 22.61 | 36.93 |
| 2017-05-24 16:51:51 | 123 | 22.61 | 36.94 |
| 2017-05-24 16:51:56 | 123 | 22.61 | 36.94 |
+---------------------+------+-------+-------+
I've tried to make this query, but it gives me an error:
ERROR 1242 (21000): Subquery returns more than 1 row
Please help me to get a correct result.
select
m.meas_time,
m.room,
(select value from meteo m1 where m1.meas_kind='T' and m.meas_time=m1.meas_time) as Temp,
(select value from meteo m2 where meas_kind='H' and m.meas_time=m2.meas_time) as Humid
from meteo m
join meteo m1
on m.meas_time=m1.meas_time
and m.room=m1.room
join meteo m2
on m.meas_time=m2.meas_time
and m.room=m2.room
group by m.room, m.meas_time;
You are overcomplicating things. A simple pivot query can give you the results you want.
SELECT
meas_time,
room,
MAX(CASE WHEN meas_kind = 'T' THEN value END) AS Temp,
MAX(CASE WHEN meas_kind = 'H' THEN value END) AS Humid
FROM meteo
GROUP BY meas_time, room
Related
Hello I have 2 tables in mysql DB:
mysql> describe lvlsupdate;
+--------------+-------------+------+-----+-------------------+-------------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+-------------------+-------------------+
| LvlsUpdateId | int | NO | PRI | NULL | auto_increment |
| UID | int | NO | MUL | NULL | |
| Nick | varchar(30) | NO | | NULL | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
| Lvl | int | YES | | NULL | |
+--------------+-------------+------+-----+-------------------+-------------------+
5 rows in set (0.02 sec)
mysql> describe players;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| UID | int | NO | PRI | NULL | auto_increment |
| Nick | varchar(30) | NO | UNI | NULL | |
| Active | tinyint(1) | NO | | NULL | |
+--------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
In one of theme there is column date which includes timestamp value.
I'd like to create query that will show me data that there will be column Nick and 7 dates (today and 6 days before). And in each row there should be nick and lvl value from each of this dates in proper column.
For now, I've created query like this:
SELECT LvlsUpdate.nick, LvlsUpdate.lvl, LvlsUpdate.date
FROM LvlsUpdate
INNER JOIN Players ON LvlsUpdate.uid = Players.uid
WHERE Players.active = 1 AND LvlsUpdate.date > date_sub(now(), interval 7 day)
which shows me list of nicks, lvls, and date but there are duplicates of nicks, it looks like this:
+------------------+------+---------------------+
| nick | lvl | date |
+------------------+------+---------------------+
| Player1 | 124 | 2020-10-11 00:01:02 |
| Player1 | 125 | 2020-10-12 00:01:03 |
| Player1 | 125 | 2020-10-13 00:01:02 |
| Player2 | 233 | 2020-10-11 00:01:02 |
| Player2 | 233 | 2020-10-12 00:01:03 |
| Player2 | 233 | 2020-10-13 00:01:02 |
| Player3 | 164 | 2020-10-11 00:01:02 |
| Player3 | 164 | 2020-10-12 00:01:03 |
| etc....
There is reference between LvlsUpdate.UID and Players.UID. There is only 1 entry per player per day.
Is it possible to do it in sql?
I have a listing_categories table that has many listing_plans and listings, and many subcategories. I am trying to write a view to show the listing categories with listing_plan count, listings count and subcategory count.
Here is my listing_categories table:
MariaDB [railsapp_development]> describe listing_categories;
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| website_id | int(11) | YES | MUL | NULL | |
| listing_category_id | int(11) | YES | | NULL | |
| name | varchar(255) | YES | | NULL | |
| slug | varchar(255) | YES | | NULL | |
| description | text | YES | | NULL | |
| category_card | text | YES | | NULL | |
| listing_card | text | YES | | NULL | |
| layout | varchar(255) | YES | | NULL | |
| status | int(11) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
| keywords | varchar(255) | YES | | NULL | |
+---------------------+--------------+------+-----+---------+----------------+
And the view I am trying to write:
create or replace view `listing_category_details` AS
select
cats1.*,
count(l.id) as listing_count,
count(cats2.id) as subcategory_count,
count(lp.id) as plan_count
from
listing_categories as cats1
left join
listings as l on cats1.id = l.listing_category_id
left join
listing_plans as lp on cats1.id = lp.listing_category_id
inner join
listing_categories as cats2 on cats1.listing_category_id = cats2.id
group by
cats1.id
order by
cats1.name asc;
The output is incorrect, it is not showing the right count, as follows:
MariaDB [railsapp_development]> select id, slug, name, listing_count, subcategory_count, plan_count from listing_category_details limit 10;
+----+-------------------+-------------------+---------------+-------------------+------------+
| id | slug | name | listing_count | subcategory_count | plan_count |
+----+-------------------+-------------------+---------------+-------------------+------------+
| 17 | ares | Ares | 22 | 22 | 22 |
| 30 | automotive | Automotive | 16 | 16 | 16 |
| 19 | crist-osinski-inc | Crist-Osinski Inc | 12 | 12 | 12 |
| 29 | esl-cologne | ESL Cologne | 20 | 20 | 20 |
| 18 | executive-office | Executive Office | 22 | 22 | 22 |
| 27 | gfinity-london | GFinity London | 24 | 24 | 24 |
| 25 | hephaestus | Hephaestus | 28 | 28 | 28 |
| 24 | iem-championship | IEM Championship | 14 | 14 | 14 |
| 26 | league-all-stars | League All Stars | 30 | 30 | 30 |
| 21 | machinery | Machinery | 14 | 14 | 14 |
+----+-------------------+-------------------+---------------+-------------------+------------+
In the above example none of the figures are corect, for instance each listing_category has exactly 2 plans.
What am I doing wrong?
Use COUNT(DISTINCT):
select cats1.*,
count(distinct l.id) as listing_count,
count(distinct cats2.id) as subcategory_count,
count(distinct lp.id) as plan_count
from listing_categories cats1 left join
listings l
on cats1.id = l.listing_category_id left join
listing_plans lp
on cats1.id = lp.listing_category_id inner join
listing_categories cats2
on cats1.listing_category_id = cats2.id
group by cats1.id
order by cats1.name asc;
COUNT() just counts the number of non-NULL values. You are joining along a hierarchy, so the rows get multiplied as you descend the hierarchy.
I need to use a data visualization tool that can only query a single source for a given chart. I have three tables with the data I need to visualize. So, I need to combine them into a single view or output table. Here are the table schemas:
MySQL [bdCaloriesNeeded]> desc activity;
+---------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+----------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | text | YES | | NULL | |
| Gender | text | YES | | NULL | |
| age | int(11) | YES | | NULL | |
| length | text | YES | | NULL | |
| weight | int(11) | YES | | NULL | |
| exercise | int(11) | YES | | NULL | |
| food_consumed | int(11) | YES | | NULL | |
| date | datetime | YES | | NULL | |
+---------------+----------+------+-----+---------+-------+
MySQL [bdCaloriesNeeded]> desc exercise;
+---------------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+---------+------+-----+---------+-------+
| Gender | text | YES | | NULL | |
| Min_Age | int(11) | YES | | NULL | |
| Max_Age | int(11) | YES | | NULL | |
| min_exercise_hours | int(11) | YES | | NULL | |
| med_exercise_hours | int(11) | YES | | NULL | |
| high_exercise_hours | int(11) | YES | | NULL | |
+---------------------+---------+------+-----+---------+-------+
MySQL [bdCaloriesNeeded]> desc food;
+---------------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+---------+------+-----+---------+-------+
| size | text | YES | | NULL | |
| min_pounds | int(11) | YES | | NULL | |
| max_pounds | int(11) | YES | | NULL | |
| min_food_oz_per_day | int(11) | YES | | NULL | |
| max_food_oz_per_day | int(11) | YES | | NULL | |
+---------------------+---------+------+-----+---------+-------+
Here's the actual source data in the above tables:
MySQL [bdCaloriesNeeded]> select * from activity;
+------+----------+--------+------+--------+--------+----------+---------------+---------------------+
| id | name | Gender | age | length | weight | exercise | food_consumed | date |
+------+----------+--------+------+--------+--------+----------+---------------+---------------------+
| 14 | spot | M | 2 | 2'7" | 13 | 5 | 13 | 2017-10-08 00:00:00 |
| 67 | princess | F | 6 | 3'3" | 75 | 3 | 15 | 2017-09-05 00:00:00 |
+------+----------+--------+------+--------+--------+----------+---------------+---------------------+
MySQL [bdCaloriesNeeded]> select * from exercise
+--------+---------+---------+--------------------+--------------------+---------------------+
| Gender | Min_Age | Max_Age | min_exercise_hours | med_exercise_hours | high_exercise_hours |
+--------+---------+---------+--------------------+--------------------+---------------------+
| M | 1 | 2 | 1 | 4 | 6 |
| M | 3 | 7 | 1 | 3 | 4 |
| M | 8 | 15 | 1 | 2 | 2 |
| F | 1 | 2 | 1 | 4 | 6 |
| F | 3 | 7 | 1 | 3 | 5 |
| F | 8 | 15 | 1 | 2 | 2 |
+--------+---------+---------+--------------------+--------------------+---------------------+
MySQL [bdCaloriesNeeded]> select * from food;
+--------+------------+------------+---------------------+---------------------+
| size | min_pounds | max_pounds | min_food_oz_per_day | max_food_oz_per_day |
+--------+------------+------------+---------------------+---------------------+
| small | 1 | 10 | 12 | 18 |
| medium | 11 | 30 | 15 | 30 |
| large | 31 | 100 | 25 | 50 |
+--------+------------+------------+---------------------+---------------------+
Here's the SQL I'm executing:
SELECT activity.id, activity.name, activity.Gender, activity.age, activity.weight, activity.exercise, activity.date, exercise.min_exercise_hours, exercise.high_exercise_hours, food.size, food.min_food_oz_per_day, food.max_food_oz_per_day
from activity, exercise, food
where (
activity.exercise between exercise.min_exercise_hours and exercise.high_exercise_hours
)
and
(
activity.weight between food.min_pounds and food.max_pounds
)
and
(
activity.Gender = exercise.Gender
)
Here's the undesired result I'm getting:
+------+----------+--------+------+--------+----------+---------------------+--------------------+---------------------+--------+---------------------+---------------------+
| id | name | Gender | age | weight | exercise | date | min_exercise_hours | high_exercise_hours | size | min_food_oz_per_day | max_food_oz_per_day |
+------+----------+--------+------+--------+----------+---------------------+--------------------+---------------------+--------+---------------------+---------------------+
| 14 | spot | M | 2 | 13 | 5 | 2017-10-08 00:00:00 | 1 | 6 | medium | 15 | 30 |
| 67 | princess | F | 6 | 75 | 3 | 2017-09-05 00:00:00 | 1 | 6 | large | 25 | 50 |
| 67 | princess | F | 6 | 75 | 3 | 2017-09-05 00:00:00 | 1 | 5 | large | 25 | 50 |
+------+----------+--------+------+--------+----------+---------------------+--------------------+---------------------+--------+---------------------+---------------------+
I'm getting two rows for Princess. I need one row for each dog. The desired result should use Princess's's weight to look up the correct range of food per day, and use her gender and age to look up the correct range of exercise.
I've been banging on this for hours, can't see what doing wrong here.
So interestingly your question says that the tables are Unrelated but they are actually related and this is the whole point of a relational database, to join data based on those relationships.
The issue is that your exercise table is only being joined on exercise hours using the between so princess matches rows 4 and 5 in the exercise table. (the first where clause matches rows 1 and 2 also but the later where clause limits the Gender)
It looks to me like you should also limit the match on the exercise table to age as well as exercise and gender
so add
and (activity.age between exercise.min_age and exercise.max_age)
Also personally i like to use JOIN clauses rather than WHERE - it keeps all the stuff together.
SELECT activity.id,
activity.name,
activity.Gender,
activity.age,
activity.weight,
activity.exercise,
activity.date,
exercise.min_exercise_hours,
exercise.high_exercise_hours,
food.size,
food.min_food_oz_per_day,
food.max_food_oz_per_day
FROM activity
JOIN exercise
ON activity.exercise BETWEEN exercise.min_exercise_hours AND exercise.high_exercise_hours
AND activity.Gender = exercise.Gender
AND activity.age BETWEEN exercise.min_age AND exercise.max_age
JOIN food
ON activity.weight BETWEEN food.min_pounds AND food.max_pounds
Since you are looking for things that may be OUTSIDE of the ranges suggested you may want to consider LEFT JOIN on the exercise and food tables, so that the dogs on the activity table that fall outside of any range will still show up (with NULL values for the missing data for the other table.)
just change the join lines to LEFT JOIN like so:
LEFT JOIN exercise
LEFT JOIN food
See also: What is the difference between "INNER JOIN" and "OUTER JOIN"?
This is my table schema:
mysql> describe stocks;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| symbol | varchar(32) | NO | | NULL | |
| date | datetime | NO | | NULL | |
| value | float(10,3) | NO | | NULL | |
| contracts | int(8) | NO | | NULL | |
| open | float(10,3) | NO | | NULL | |
| close | float(10,3) | NO | | NULL | |
| high | float(10,3) | NO | | NULL | |
| low | float(10,3) | NO | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
9 rows in set (0.00 sec)
I added two new columns named high and low so they are empty now.
My goal is fill up these columns with the relative max(value),min(value) based on each daytime!
My first insight is this query:
select distinct DATE(date),max(value) as max,min(value) as min from stocks GROUP BY DATE(date);
...
| 2017-02-20 | 19130.000 | 18875.000 |
| 2017-02-21 | 19170.000 | 18780.000 |
| 2017-02-22 | 19125.000 | 18745.000 |
| 2017-02-23 | 18980.000 | 18765.000 |
| 2017-02-24 | 18840.000 | 18505.000 |
+------------+-----------+-----------+
that achieve the first step, now I should join these results with each rows:
| 900363 | FIB7C | 2017-02-20 17:49:44 | 18930.000 | 1 | 0.000 | 0.000 | 0.000 | 0.000 |
and insert the correct value based on DATE(date) but I still not catch to do with INSERT INTO.
Thanks for helps regards.
You can do this with a join in the update along with an aggregation to calculate the values:
update stocks s join
(select date(date) as d, max(value) as dhigh, min(value) as dlow
from stocks s
group by date(date)
) sd
on date(s.date) = sd.d
set s.high = sd.dhigh,
s.low = sd.dlow;
I have mysql query :-
select id,CustomerName, Scenario,StepNo,InTransit,IsAlef,Min(RunNo) as run,IsDominant,IsActive from RequestInfo
group by CustomerName, Scenario,StepNo,InTransit,IsAlef,RunNo
having concat(CustomerName,Scenario,StepNo,InTransit,IsAlef,count(RunNo)) in
(select concat(CustomerName,Scenario,StepNo,InTransit,IsAlef,Min(Total)) from
(select CustomerName, Scenario,StepNo,InTransit,IsAlef,RunNo, count(RunNo) Total from RequestInfo
group by CustomerName, Scenario,StepNo,InTransit,IsAlef,RunNo
) b
group by CustomerName, Scenario,StepNo,InTransit,IsAlef);
which gives output :-
+------+--------------+--------------+--------+-----------+--------+------+------------+----------+
| id | CustomerName | Scenario | StepNo | InTransit | IsAlef | run | IsDominant | IsActive |
+------+--------------+--------------+--------+-----------+--------+------+------------+----------+
| 1 | Cleartrip | SearchFlight | 1 | No | No | 1 | NULL | NULL |
| 327 | HotStar | SearchTv | 1 | No | No | 1 | NULL | NULL |
| 836 | NDTV | LiveTv | 1 | No | No | 2 | NULL | NULL |
| 1090 | YATRA | SearchFlight | 1 | No | No | 2 | NULL | NULL |
+------+--------------+--------------+--------+-----------+--------+------+------------+----------+
i want to set the last two columns as "Yes" only for the rows which are been shown in the above result.