MYSQL Select max value in multi column in a date - mysql

Suppose I have table called "bowlmark" and the summary of table as below link:
(this table is recording the bowling marks for each bowler)
Here is the sample table summary:
bowler_id---record_date---round1mark---round2mark
101---2018-06-02---100---164
102---2018-06-02---102---120
101---2018-06-03---150---124
103---2018-06-03---200---122
I want to output the highest marks in each record day and show the bowler id
For the above example, I want the output to be:
date:2018-06-02, bowler_id:101, highestmark: 164
date:2018-06-03, bowler_id:103, highestmark: 200 .
How to write this SQL query? Thanks.

It's a little ugly, but I was able to do it this way:
SELECT b.bowler_id, a.* FROM (
SELECT record_date, MAX(GREATEST(round1mark, round2mark)) AS greatest
FROM bowlers
GROUP BY record_date
) a
INNER JOIN bowlers b ON
a.record_date = b.record_date AND
a.greatest = GREATEST(b.round1mark, b.round2mark)
SQLFiddle here: http://sqlfiddle.com/#!9/3718ec/17

You could use greatest and an inner join on the subquery for max round mark
select m.bowler_id, m.record_date
, greatest(round, round2, round3, round4, round5, round6) highest_mark
from bowlmark m
inner join (
select record_date
, max(greatest(round, round2, round3, round4, round5, round6)) as max_round
from bowlmark
group by record_date
) t on t.record_date = m.record_date
and greatest(round, round2, round3, round4, round5, round6) = t.max_round
anyway a proper datababase normalization could help you to avoid this kind of problems

Related

AVG join result in other table

I've got a query with avg results. In another table I have the results of that
avg result in text.
Right now this is my query:
select round(avg(breed_ratings.rating)) as result, breed_ratings.score_name, count(*) as total, breeds.name_en
from breed_ratings
inner join breeds on breeds.id = breed_ratings.breed_id
where breeds.id = 188
group by score_name, breeds.name_en
The rating_result table looks like this:
id
rating
result_text
How can I get the result_text in this query?
Please help me out.
--EDIT
I need to get the result from the image below in text.
So I have another table where this is stored I need to get the result_nl where it matches the rating:
Desired result (if rating is 5):
result: 5
score_name: ADULT_FRIENDLY
total: 117
name_en: American Staffordshire Terrier
result_nl: I am extremely dominant
I think you want to join the average to the first rating in rating_results where the average is bigger than the listed rating there. If so:
select br.*, rr.result_text
from (select round(avg(br.rating)) as result, br.score_name, count(*) as total, b.name_en
from breed_ratings br join
breeds b
on b.id = br.breed_id
where b.id = 188
group by br.score_name, b.name_en
) br left join
(select rr.*, lead(rr.rating) over (order by rr.rating) as next_rating
from rating_result rr
) rr
on br.result >= rr.rating and
(br.result < rr.next_rating or rr.next_rating is null)

The query is not giving a desired output which I want

Query with OR which outputs wrong
SELECT DISTINCT
sm___employees.id,
sm___employees.employee_code,
sm___employees.leaving_date,
sm___employees.name_of_employee,
sm___employees.position,
sm___employees.rating,
sm___employees.entry_date
FROM
sm___employees
JOIN
sm___employee_skills
ON
sm___employees.id=sm___employee_skills.employee_id
WHERE
((sm___employee_skills.skill_id=1 AND sm___employee_skills.ans LIKE '%MBA%')
**OR**
(sm___employee_skills.skill_id=5 AND sm___employee_skills.ans IN (3)))
AND
sm___employees.rating IN (1)
ORDER BY
sm___employee_skills.date DESC
But I want it by And
SELECT DISTINCT
sm___employees.id,
sm___employees.employee_code,
sm___employees.leaving_date,
sm___employees.name_of_employee,
sm___employees.position,
sm___employees.rating,
sm___employees.entry_date
FROM
sm___employees
JOIN
sm___employee_skills
ON
sm___employees.id=sm___employee_skills.employee_id
WHERE
((sm___employee_skills.skill_id=1 AND sm___employee_skills.ans LIKE '%MBA%')
**AND**
(sm___employee_skills.skill_id=5 AND sm___employee_skills.ans IN (3)))
AND
sm___employees.rating IN (1)
ORDER BY
sm___employee_skills.date DESC
When am using first query with OR of MBA or 3, It gives me result for both which is correct as per OR operation
I want only those records which are having MBA AND 3 which gives me blank records when there are records available with this comparison
So please help me to resolve this.
Thank you in advance
To start with: DISTINCT often indicates a badly written query. This is the case here. You are joining records only to dismiss them later. If you want employee records, then select from the employee table. If you have criteria on the skills table check this in the WHERE clause. Don't join.
Then the WHERE clause looks at one row at a time. So neither skill_id = ... AND skill_id = ... nor skill_id = ... OR skill_id = ... can work for you. You must look up the skills table twice:
SELECT
id,
employee_code,
leaving_date,
name_of_employee,
position,
rating,
entry_date
FROM sm___employees
WHERE rating IN (1)
AND id IN
(
SELECT employee_id
FROM sm___employee_skills
WHERE skill_id = 1 AND ans LIKE '%MBA%'
)
AND id IN
(
SELECT employee_id
FROM sm___employee_skills
WHERE skill_id = 5 AND ans IN (3)
);
And here is a way to look up skills just once:
SELECT
id,
employee_code,
leaving_date,
name_of_employee,
position,
rating,
entry_date
FROM sm___employees
WHERE rating IN (1)
AND id IN
(
SELECT employee_id
FROM sm___employee_skills
WHERE (skill_id = 1 AND ans LIKE '%MBA%')
OR (skill_id = 5 AND ans IN (3))
GROUP BY employee_id
HAVING COUNT(DISTINCT skill_id) = 2 -- both skills
);
It seems strange though that you consider ans to be a string in one place (ans LIKE '%MBA%') and a number in another (ans IN (3)).
UPDATE: If you want to sort by skill date, you should consider by which skill's date. For this to happen, you would join, but not join the skills table, but the skills aggregate result. E.g.:
SELECT
e.id,
e.employee_code,
e.leaving_date,
e.name_of_employee,
e.position,
e.rating,
e.entry_date
FROM sm___employees e
JOIN
(
SELECT employee_id, MAX(date) AS max_date
FROM sm___employee_skills
WHERE (skill_id = 1 AND ans LIKE '%MBA%')
OR (skill_id = 5 AND ans = 3)
GROUP BY employee_id
HAVING COUNT(DISTINCT skill_id) = 2 -- both skills
) s ON s.employee_id = e.id
WHERE e.rating = 1
ORDER BY s.max_date;
Please try this :
SELECT DISTINCT
sm1.id,
sm1.employee_code,
sm1.leaving_date,
sm1.name_of_employee,
sm1.position,
sm1.rating,
sm1.entry_date
FROM sm___employees sm1
LEFT JOIN sm___employee_skills sm2 ON sm1.id = sm2.employee_id
WHERE ((sm2.skill_id=1 AND sm2.ans LIKE '%MBA%')
AND (sm2.skill_id=1 AND sm2.ans=3))
AND sm1.rating IN (1)
ORDER BY sm2.date DESC;

SELECT group by twice

I'm not strong in DB at all and I need your help.
I need SQL request with GROUP by twice.
Example of my data in table
<table border="1" style="border-collapse:collapse">
<tr><th>id</th><th>market_id</th><th>price</th><th>low</th><th>high</th><th>symbol</th><th>created_at</th></tr>
<tr><td>1</td><td>1</td><td>5773.8</td><td>5685</td><td>6020</td><td>btcusd</td><td>2017-10-27 16:46:10</td></tr>
<tr><td>2</td><td>1</td><td>0.4274</td><td>0.39</td><td>0.43983</td><td>iotusd</td><td>2017-10-27 16:46:11</td></tr>
<tr><td>3</td><td>1</td><td>0.20026</td><td>0.1986</td><td>0.20352</td><td>xrpusd</td><td>2017-10-27 16:46:12</td></tr>
<tr><td>4</td><td>2</td><td>5771</td><td>5685</td><td>6020</td><td>btcusd</td><td>2017-10-27 16:46:18</td></tr>
<tr><td>5</td><td>2</td><td>0.4274</td><td>0.39</td><td>0.43983</td><td>iotusd</td><td>2017-10-27 16:46:18</td></tr>
<tr><td>6</td><td>2</td><td>0.20026</td><td>0.1986</td><td>0.20352</td><td>xrpusd</td><td>2017-10-27 16:46:19</td></tr>
<tr><td>7</td><td>1</td><td>5773.1</td><td>5685</td><td>6020</td><td>btcusd</td><td>2017-10-27 16:46:25</td></tr>
<tr><td>8</td><td>1</td><td>0.4274</td><td>0.39</td><td>0.43983</td><td>iotusd</td><td>2017-10-27 16:46:25</td></tr>
<tr><td>9</td><td>1</td><td>0.20026</td><td>0.1986</td><td>0.20352</td><td>xrpusd</td><td>2017-10-27 16:46:26</td></tr>
<tr><td>10</td><td>2</td><td>5773.1</td><td>5685</td><td>6020</td><td>btcusd</td><td>2017-10-27 16:46:32</td></tr>
<tr><td>11</td><td>2</td><td>0.42741</td><td>0.39</td><td>0.43983</td><td>iotusd</td><td>2017-10-27 16:46:32</td></tr>
<tr><td>12</td><td>2</td><td>0.20026</td><td>0.1986</td><td>0.20352</td><td>xrpusd</td><td>2017-10-27 16:46:33</td></tr></table>
I would like to get latest data for every market_id and symbol
That's mean I need somethind like that in the end :
- id market_id symbol
- 7 1 btcusd
- 8 1 iotusd
- 9 1 xrpusd
- 10 2 btcusd
- 11 2 iotusd
- 12 2 xrpusd
Really need help, a little bit blocked.
You are almost there. Try this
SELECT c.*
FROM CRYPTO as C
JOIN (
SELECT market_id, symbol, MAX(id) as maxid
FROM CRYPTO
GROUP BY market_id, symbol
) AS C2
ON C2.maxid = C.id and C.market_id = c2.market_id and c.symbol = c2.symbol
Along these lines...
SELECT MAX(id), market_id, symbol
FROM crypto
GROUP BY market_id, symbol
Here's my comment stated as SQL.
SELECT A.ID, A.MarketID, A.Symbol, A.Price, A.Low, A.High
FROM CRYPTO A
INNER JOIN (SELECT max(Created_at) MCA, Market_ID, Symbol
FROM crypto
GROUP BY Market_ID, Symbol) B
on A.Created_At = B.MCA
and A.market_ID = B.Market_ID
and A.Symbol = B.Symbol
What this does:
The derived table (aliased B) generates 1 line for each market_ID and symbol having the max created_at time. It then uses this derived table set to join back to the base set (aliased A) to limit the data to just those having the max created_at. this allows us to show the whole record from A for each unique market_Id and symbol; but only for records having the max created_at.
Other engines would allow you to use a cross apply or an analytic to obtain the desired results.
I tried these requests
SELECT * FROM CRYPTO as C3
JOIN (
SELECT MAX(id) as max
FROM CRYPTO as C1
GROUP BY symbol
) AS C2
ON C2.max = C3.id
SELECT M.id, M.name, R.symbol FROM MARKET AS M
JOIN (
SELECT DISTINCT C.symbol, C.market_id
FROM CRYPTO as C
) as R
ON M.id = R.market_id
But finally I did not find the good combination.

Query to join 2 tables and keep only 1 row from one of the tables

I have 2 tables (item and item_historic) and i'm looking for a query that keep the last item_historic line (max date) and join it to the item table.
item :
id_item state_item
5560 complete
5570 removed
item_historic :
id_historic id_item state_historic date
2002 5560 declared 2011-01-13 13:32:15
2198 5560 complete 2011-03-14 11:44:40
1780 5570 declared 2011-03-15 15:26:55
2208 5570 removed 2011-04-15 08:17:59
result :
id_item id_historic state_item date state_historic
5560 2198 complete 2011-03-14 11:44:40 complete
5570 2208 removed 2011-04-15 08:17:59 removed
I want one id_item only.
I hope that make sense and thanks in advance.
EDIT : wrong result and my question is what should the query look like ?
Tried :
select ah.id_item, ah.id_historic, at.state, date, ah.id_type, ah.state_item from item at left join item_historic ah on ah.id_item = at.id_item group by ah.id_item order by max(date) ;
In MySQL, the not exists approach is often the most efficient:
select ah.id_attestation, ah.id_historic, at.state, date, ah.id_type, ah.state_aft
from `via-energica_plateforme`.attestation at left join
`via-energica_plateforme`.attestation_historic ah
on ah.id_attestation = at.id_attestation
where not exists (select 1
from `via-energica_plateforme`.attestation_historic ah2
where ah2.id_item = ah.id_item and
ah2.date > ah.date
);
This query will work best with an index on attestation_historic(id_item, date).
The not exists clause takes some getting used to in this context. It is saying "choose the row from ah where there is no more recent row from the table" -- which is that same as "get the maximum date". The advantage in MySQL is that no aggregation is required, and aggregation can be an expensive operation. But, for performance, you really need to compare the two approaches.
The following is a way of doing it with a sub-query:
SELECT i.id_item, ih.id_historic, i.state_item, sq.max_date as `date`, ih.state_historic
FROM attestation i
INNER JOIN (SELECT id_item, MAX(`date`) AS max_date FROM attestation_historic GROUP BY id_item) AS sq ON i.id_item = sq.id_item
INNER JOIN attestation_historic ih ON i.id_item = ih.id_item AND sq.max_date = ih.`date`;
Maybe there's another way, but this would work:
SELECT t.id_item, t.id_historic, i.state_item, t.date, t.state_historic FROM item i
LEFT JOIN
(SELECT * FROM (SELECT *
FROM id_historic ORDER BY DATE DESC) t GROUP BY t.`id_item`
) t ON t.id_item = i.id_item ORDER BY t.date;

Inner query is difficult to write

I have two tables:
customer with schema_id
Schema table has: schema_id, period, amt, updated_date
I need to take join of customer and schema but only retrieve the latest record joined and not the others.
customer table
cust_id name schema_id
1 ABC 1
Schema table
schema_id period amt updated_date
1 1 100 2010-4-1
1 2 150 2011-4-1
If you need the max(updated_date) for each schema_id, then you can use an subquery:
select c.cust_id, c.name, c.schema_id, s.period, s.amt, s.updated_date
from customer c
inner join
(
select s1.schema_id, s1.period, s1.amt, s1.updated_date
from `schemas` s1
inner join
(
select schema_id, max(updated_date) MaxDate
from `schemas`
group by schema_id
) s2
on s1.schema_id = s2.schema_id
and s1.updated_date = s2.maxdate
) s
on c.schema_id = s.schema_id
See SQL Fiddle with Demo
The subquery is then used in a join back to your table to return the rows that have the matching date and schema_id.
If I understood your problem, you need to take lastest register of the "schema".
I think you need to use max() function. So, try the query below:
select *
from customer c,
schema s
where c.schema_id = s.schema_id
and s.updated_date = ( select max(s2.updated_date)
from schema s2
where s2.schema_id = s.schema_id
)
Regards!
Edmilton