ADD:
SQL query:
SELECT s.name
, d.feeling
, COUNT(1) AS times
FROM data_table d
, staff s
WHERE d.nid = s.id
AND d.project_id = 1
AND d.crawl_time BETWEEN '2018-10-17' AND '2018-10-24'
AND LENGTH(TRIM(d.feeling)) > 0
GROUP
BY d.nid
, d.feeling
ADD (END)
I write a sql to query the times of each body's feelings group by name and feeling. Here is the result.
-- a certain sql returns, not an existing table --
`name` `feeling` `times` (expect)
Jack happy 10 0.45
Jack sad 7 0.31
Jack common 5 0.22
Lily happy 3 0.27
Lily sad 6 0.54
Lily common 2 0.18
Sam happy 6 0.42
Sam sad 7 0.5
Sam common 1 0.07
Now the aim is to calculate the ratio of everyone's feelings. For example, the happy feeling of Jack takes 10/(10+7+5) of his feelings, and for sad feeling is 7/(10+7+5).
When using SUM(result.count) and GROUP BY name to figure, the sad or common feelings cannot show. Then I use subquery, but the table does not exist. Is there anyway to work without creating a view?
One solution which should work on any version of MySQL uses a subquery to find the sum of times for each name, and then joins to it:
SELECT
t1.name,
t1.feeling,
t1.times,
t1.times / t2.times_sum AS feeling_ratio
FROM yourTable t1
INNER JOIN
(
SELECT name, SUM(times) AS times_sum
FROM yourTable
GROUP BY name
) t2
ON t1.name = t2.name;
If you are using MySQL 8+ or later, and have access to analytic functions, then there is simpler way of writing this:
SELECT
t1.name,
t1.feeling,
t1.times,
t1.times / SUM(t1.times) OVER (PARTITION BY t1.name) AS feeling_ratio
FROM yourTable t1;
Related
So, i have a db.measurements that look like this
Date
Value
equipement_id
operator_id
20-03-12
0.45
1
1
20-03-15
0.36
2
1
20-03-19
0.39
1
3
20-04-02
0.37
1
2
And a db.operators and db.equipements that look like this
operator_id
operator_name
1
John
2
Mat
3
Brad
4
Alfred
equipement_id
equipement_model
1
Model-ABC
2
Model-XYZ
3
Model-SuperX
4
Model-Wifi
So i need to do a query to select all the data from db.measurements but replacing the "id" of both equipement and operator with the respective name/model. What would be the best way to do it?
I can do SELECT * FROM db.measurements; but cant figure it out how to use REPLACE in this case since tables are longer.
Cant figure how join works. This query is not valid and returs nothing on mysql workbench
SELECT date, value, db.operators.operator_name as operator_name
FROM db.measurements
INNER JOIN db.operators ON db.operators.operator_id = operator_id;
Thanks
Just join again with db.equipements the same way.
SELECT m.date, m.value, o.operator_name, e.equipement_model
FROM db.measurements AS m
INNER JOIN db.operators AS o ON o.operator_id = m.operator_id
INNER JOIN db.equipements AS e ON e.equipement_id = m.equipement_id
I am trying to find the second max based on two different categories. I can use analtycal function or logic to get this. I have been trying to find this through a logic.
My question is I am trying to fetch the records of second most taken exam per country by unique students.
T1
Exam_ID Student_ID
123 553
123 457
345 563
567 765
678 543
678 543
987 123
678 123
T2
Exam_ID Exam_name Country_name
123 SAT USA
345 CAT USA
567 GRE USA
678 TOEFL UK
987 IELTS UK
222 CBAP UK
This is what I tried so far,
select count(distinct T1.Student_ID) count_user,
t2.Country_name,t2.Exam_name
from T1
join T2
on T1.Exam_ID = T2.Exam_ID
group by t2.Exam_name, t2.Country_name
By doing this I am able to get the unique student count based on each exam and country.
How can I get the second max no of exams taken by unique students based on the country?
I'm not sure I fully understand what you mean by your question.
Could you post the expected result along with what you are getting now?
In the mean time, I'm taking a guess that exam_id 678 in the UK (with 3 students) is the top result and 987 in the UK is the "second top result"???
If so, Row_number () might work for you. Bear in mind that row_number is usually an expensive operation in relational databases as it involves a redistribution and a sort. A similar function Rank () may be better for you depending upon how you want to handle ties. The syntax is similar, you could try both.
Try modifying your query as follows:
select count(distinct T1.student_id) count_user, Country_name, Exam_name,
row_number () over (partition by country_name order by count_user desc) as row_num
...
If that gives you the numbering you want, you can then restrict the output using the qualify clause i.e.
qualify row_num = 2
You may need to wrap the whole thing in a derived table as follows:
select count_user, country_name, exam_name,
row_number () over (partition by country_name order by count_user desc) as row_num
from (
select count(distinct T1.Student_ID) count_user,
t2.Country_name,t2.Exam_name,
from T1 join T2
on T1.Exam_ID = T2.Exam_ID
group by t2.Exam_name, t2.Country_name
) detail_recs
qualify row_num = 2
I have a table, it similar with this table
ID Name Age Status
1 John 32 Life
2 Andre 99 Life
3 Anton 89 Dead
4 Maria 99 Life
5 Mario 13 Life
6 Santi 89 Dead
7 Anggy 56 Dead
8 Amir 99 Life
I want to do something like this
1. Group rows by status (Life)
2. Get the max Age from that group (99) (only the max number need)
4. Make new group by age and sort it by ID.
The result will be
8 Amir 99 Life
4 Maria 99 Life
2 Andre 99 Life
Any way to use only 1 line query for that job? with some (php) data procesing its not to hard to get the result i want, but i want to make code as clean as posible, so maybe i can do that 3 step in just a single query?
I think the right logic is:
select t.id, t.name, t.age, t.status
from table t join
(select max(t2.age) from table t2 where t2.status = 'life') m
on t.age = m.age
where t.status = 'life'
order by id desc;
select id, name, age, status
from thetable
where age =
(select max(age)
from thetable
where status="Life"
)
where status="Life"
order by id desc
Use the below mentioned query :
SELECT
*
FROM
t4
CROSS JOIN
(SELECT
MAX(`age`) AS 'age'
FROM
t4
WHERE
`status` = 'Life') AS t5
WHERE
`status` = 'Life' AND t4.`age` = t5.age
ORDER BY `id` DESC;
Check SQLFiddle
I have tried this multiple distinct from MySQL and I cant seem to get anything to work... I have a table that is a history table. The appartments can be found many times from the same building with different status. I need to find the newest one for each appartment (the one with the highest id ORDER BY id)
id building appartment_id status
208 1 2 2
209 1 3 2
210 1 4 2
211 1 5 2
212 1 6 2
213 1 7 2
214 1 2 1
215 1 2 3
But how do I do that?! :S
I have tried this:
SELECT *, GROUP_CONCAT(appartment_id, building)
FROM `ib30_history`
group by appartment_id, building
order by id DESC
It seems to work but im not sure that is the right way of doing it and the code that uses the output seems to make funny things running through the data so im not sure it really works!
SELECT yourtable.id, yourtable.building, yourtable.appartment_id, yourtable.status
FROM yourtable
INNER JOIN (
SELECT MAX(id) AS id
FROM yourtable
GROUP BY building, appartment_id
) AS child ON yourtable.id = child.id
Get rid of distinct and use something like:
GROUP BY building , appartment_id
What you're looking for is called GROUP BY, and MySQL's documentation knows a lot about how it's to be used. At the timeI type this, the OP doesn't contain a query so I cannot give you an example...
SELECT a.*
FROM table_name a
INNER JOIN
(SELECT MAX(id) as max_id
FROM table_name
GROUP BY appartment_id) b
ON (b.max_id = a.id)
I am trying to select data from multiple tables which uses an AVG in the WHERE clause.
SELECT company_metrics.*, companies.company_name, companies.permalink
FROM company_metrics LEFT JOIN companies
ON companies.company_id = company_metrics.company_id
WHERE MONTH(date) = '04' AND YEAR(date) = '2011'
HAVING (SELECT avg(company_unique_visitors)
FROM (SELECT company_metrics.company_unique_visitors
FROM company_metrics
ORDER BY company_metrics.date DESC LIMIT 3)
average ) >'2000'
ORDER BY date DESC
Example Data:
###Company Metrics#### Table
company_id company_unique_visitors date
----------- ----------------------- ----
604 2054 2011-04-01
604 3444 2011-03-01
604 2122 2011-02-01
604 2144 2011-01-01
604 2001 2010-12-01
602 2011 2011-04-01
602 11 2011-03-01
602 411 2011-02-01
602 611 2011-01-01
602 111 2010-12-01
EDIT
I would like only the 3 latest numbers from company_unique_visitors AVG'ed
/EDIT
So the query would select company_id 604 but it wouldn't select company_id 602 because 602 doesn't have an AVG greater than 2000.
I need help writing the correct query to do as I have described. I can clarify if needed.
Thanks for your help!
There are several problems with your query as written. I'm not completely clear as to the structure of all the tables, but I believe I understand the gist based on the query you posted. Your first problem with the posted query is that you're not grouping by or using any aggregates in the query where you're using the HAVING clause. You use aggregates in one of the subqueries, but the HAVING where it is right now doesn't make much sense.
I believe you wanted to group by the company_id before you did an aggregate of the averages, so I made that the primary group by on the outer query. You were also using too many nested queries to accomplish what was was a seemingly simple task of only selecting the 3 most recent measurements. I moved that subquery into the primary join so that the data was only selected once and in a logical way.
And, without further ceremony, here's the fixed query:
SELECT limited_metrics.*, companies.company_name, companies.permalink,
avg(limited_metrics.company_unique_visitors) AS avg_visitors
FROM
(SELECT *
FROM company_metrics
ORDER BY company_metrics.date DESC LIMIT 3) AS limited_metrics
LEFT JOIN companies
ON companies.company_id = limited_metrics.company_id
WHERE MONTH(limited_metrics.date) = '04' AND YEAR(limited_metrics.date) = '2011'
GROUP BY companies.company_id
HAVING avg_visitors > 2000
Ok based off of Jared Harding's answer and this post: Moving average - MySQL
I was able to figure out the query.
SELECT metrics.*,companies.company_name,companies.permalink
FROM (SELECT company_id,AVG(company_unique_visitors) AS met_avg
FROM company_metrics
WHERE `date` BETWEEN DATE_SUB(NOW(), INTERVAL 4 MONTH) AND NOW()
GROUP BY company_id HAVING met_avg>2000) AS metrics
LEFT JOIN companies ON companies.company_id=metrics.company_id
Thanks Jared for all your help!