I have a MySQL table as below
ID SHEET_NUMBER DAYS RESULT
1 55201 9 10
2 55209 28 25.5
3 55209 28 27.9
4 38558 7 12
5 38552 5 19
6 38559 5 5
I want to select only rows with firstly matching sheet numbers & only if there if there is a matching pair of 28 days specimens
so if there is only one 28 day it will select nothing but if there is at least 2x 28 day it will get both rows
I'm totally lost, i know i should be using group by.. but i'm unsure of its use.
thankyou
Can you try the following query:
SELECT *
FROM test
WHERE sheet_number IN (
SELECT sheet_number
FROM test
WHERE days = 28
GROUP BY sheet_number
HAVING COUNT(*) >= 2
);
Here's the SQL Fiddle.
First, write a query that finds sheet_number with two or more rows with days value of 28.
SELECT d.sheet_number
FROM my_table_below d
WHERE d.days = 28
GROUP BY d.sheet_number
HAVING COUNT(1) > 1
With that query, we can use that as an inline view, and join back to the original table to find the matching rows:
SELECT t.*
FROM ( SELECT d.sheet_number
FROM my_table_below d
WHERE d.days = 28
GROUP BY d.sheet_number
HAVING COUNT(1) > 1
) m
JOIN my_table_below t
ON t.sheet_number = m.sheet_number
AND t.days = 28
ORDER BY t.sheet_number, t.id
Omit the condition t.days = 28 on the outer query, if the specification is to return all of the rows for the sheet_number, not just the rows with days=28. (The specification is a bit unclear.)
Related
This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 1 year ago.
I have a simple table:
id
temperature
timestamp
17
23
1630770051
18
24
1630772051
4799
35
1632140689
I want max(temperature) from today or yesterday
Example 1)
SELECT max(temperature), DAY(FROM_UNIXTIME(timestamp))
FROM `zimmer_raumdaten`
group by DAY(FROM_UNIXTIME(timestamp));
max(temperatur) DAY(FROM_UNIXTIME(timestamp))
26.70 4
26.60 5
23.90 6
44.10 7
28.00 8
35.30 9
37.80 10
31.60 11
36.70 12
36.60 13
38.30 14
26.90 15
27.10 16
46.00 17
47.90 18
23.00 19
25.00 20
Result looks good.
But when I`m trying to fetch only one result for example for today - the result mixes up the rows.
SELECT max(temperature), DAY(FROM_UNIXTIME(timestamp)), id
FROM `zimmer_raumdaten`
where DAY(FROM_UNIXTIME(timestamp)) = DAY(NOW());
max(temperatur)
DAY(FROM_UNIXTIME(timestamp))
id
25.00
20
4977
The id is not correct - the row 4977 has temperature 19.00.
I appreciate every kind of ideas/thoughts on the SQL Statement.
cheers
You are misusing MySQL's notorious nonstandard extension to GROUP BY.
Under that extension's rule, your second query is equivalent to using ANY_VALUE() on your id column. That means MySQL is free to choose any row to fulfill that value.
SELECT max(temperature), DAY(FROM_UNIXTIME(timestamp)),
ANY_VALUE(id) /* <- bad. bad. bad. */
FROM `zimmer_raumdaten`
where DAY(FROM_UNIXTIME(timestamp)) = DAY(NOW());
If you want to find the id of the row containing the highest temperature for the day in question, you need a subquery.
SELECT MAX(temperature) temperature,
DAY(FROM_UNIXTIME(timestamp))) day
FROM zimmer_raumdaten
GROUP BY DAY(FROM_UNIXTIME(timestamp)))
Then you incorporate that query into a main query to recover the detail row from your table matching that temperature.
SELECT a.temperature,
b.day,
a.id
FROM zimmer_raumdaten a
JOIN (
SELECT MAX(temperature) temperature,
DAY(FROM_UNIXTIME(timestamp))) day
FROM zimmer_raumdaten
GROUP BY DAY(FROM_UNIXTIME(timestamp)))
) b ON a.temperature = b.temperature
AND DAY(FROM_UNIXTIME(a.timestamp)) = b.day
WHERE b.day = DAY(NOW())
I´m trying to do some analysis in the following data
WeekDay Date Count
5 06/09/2018 20
6 07/09/2018 Null
7 08/09/2018 19
1 09/09/2018 16
2 10/09/2018 17
3 11/09/2018 24
4 12/09/2018 25
5 13/09/2018 24
6 14/09/2018 23
7 15/09/2018 23
1 16/09/2018 9
2 17/09/2018 23
3 18/09/2018 33
4 19/09/2018 22
5 20/09/2018 31
6 21/09/2018 17
7 22/09/2018 10
1 23/09/2018 12
2 24/09/2018 26
3 25/09/2018 29
4 26/09/2018 27
5 27/09/2018 24
6 28/09/2018 29
7 29/09/2018 27
1 30/09/2018 19
2 01/10/2018 26
3 02/10/2018 39
4 03/10/2018 32
5 04/10/2018 37
6 05/10/2018 Null
7 06/10/2018 26
1 07/10/2018 11
2 08/10/2018 32
3 09/10/2018 41
4 10/10/2018 37
5 11/10/2018 25
6 12/10/2018 20
The problem that I want to solve is: I want to create a table with the average of the 3 last same weekdays related to the day. But, when there is a NULL in the weekday, I want to ignore and do the average only with the remain numbers, not count NULL as an 0. I will give you an example here:
The date in this table is day/month/year :)
Ex: On day 12/10/2018, I need the average from
the days 05/10/2018; 28/09/2018; 21/09/2018. These are the last 3 same weekday(six) as 12/10/2018.
. Their values are Null; 29; 17. Then the result of this average must be 23, because I need to ignore the NULL, and not be 15,333.
How can I do this?
The count() function ignores nulls (i.e. does NOT increment if it encounters null) so I suggest you simply count the values then may contain the nulls you wish to ignore.
dow datecol value
6 21/09/2018 17
6 28/09/2018 29
6 05/10/2018 Null
e.g. sum(value) above = 46, and the count(value) = 2 so the average is 23.0 (and avg(value) will also return 23.0 as it also ignores nulls)
select
weekday
, `date`
, `count`
, (select (sum(`count`) * 1.0) / (count(`count`) * 1.0)
from atable as t2
where t2.weekday = t1.weekday
and t2.`date` < t1.`date
order by t2.`date` DESC
limit 3
) as average
from atable as t1
You could just use avg(count) in the query above, and get the same result.
ps. I do hope you do NOT use count as a column name! I also would suggest you do NOT use date as a column name either. i.e. Avoid using SQL terms as names.
SELECT WeekDay, AVG(Count)
FROM myTable
WHERE Count IS NOT NULL
GROUP BY WeekDay
Use IsNULL(Count,0) in your Select
SELECT WeekDay, AVG(IsNULL(Count,0))
FROM myTable
GROUP BY WeekDay
First off, you need to get the number of instances of that weekday in the data since you just need the last 3 same week days
create table table2
as
select
row_number() over(partition by weekday order by date desc) as rn
,weekday
,date
,count
from table
From here, you can get what you want. With you explanation, you don't need to filter out the NULL values for count. Just doing the avg() aggregation will simply ignore it.
select
weekday
,avg(count)
from table2
where rn in (1,2,3)
group by weekday
I am running the following query to understand to get users' first attempt to answer a question listed next to their second attempt.
SELECT
s.id AS attempt_id_first, m.id AS attempt_id_second, s.user_id
FROM
attempt s
INNER JOIN attempt m on s.user_id = m.user_id
WHERE
s.id<m.id
I end up with this:
attempt_first attempt_second user_id
7 17 1
9 10 2
9 15 2
10 15 2
4 6 9
24 25 15
29 34 19
29 36 19
34 36 19
I would like to have a new column that counts the number of attempts by users so that:
7 17 1 1
9 10 2 3
9 15 2 3
10 15 2 3
4 6 9 1
24 25 15 1
29 34 19 3
29 36 19 3
34 36 19 3
I am sure this is trivial, but I cannot get it to work. Help anyone?
I think this is it: Just display the results, and throw in an extra count subquery:
select
userid,
id,
(select
count('x')
from
attempt x
where
x.userid = a.userid) as attempcount
from
attempt a
If you like to keep the first and second attempt in separate columns, you can of course embed the subselect in your original query.
It seems wrong, though. Firstly, you need to have at least two attemps, otherwise none will show. You can solve that by changing inner join to left join and move the condition in the where clause to that join. Secondly, the 'second attempt' is not the second attempt per say. Actually, for each of the attempts you get all next attempts. Look at the example of user 2. You accidentally get three rows (where there are three attemps), but you get attempt 9 and 10, as well as attempt 9 and 15 as well as 10 and 15. 9, 15 is incorrect, since 15 isn't the attempt that followed 9. The more attempts a user has, the more of these false results you will get.
If you want one attempt listed next to the next one, with the count, I would suggest:
SELECT s.user_id, s.id AS attempt_id_first,
(select s2.id
from attempt s2
where s2.user_id = s.user_id and
s2.id > s.id
order by s2.id
limit 1
) as attempt_id_second,
(select count(*)
from attempt s3
where s3.user_id = s.user_id
) as totalAttempts
FROM attempt s ;
This only lists each attempt once with the next one. The count is included as the last column.
I have a table with columns similar to below , but with about 30 date columns and 500+ records
id | forcast_date | actual_date
1 10/01/2013 12/01/2013
2 03/01/2013 06/01/2013
3 05/01/2013 05/01/2013
4 10/01/2013 09/01/2013
and what I need to do is get a query with output similar to
week_no | count_forcast | count_actual
1 4 6
2 5 7
3 2 1
etc
My query is
SELECT weekofyear(forcast_date) as week_num,
COUNT(forcast_date) AS count_forcast ,
COUNT(actual_date) AS count_actual
FROM
table
GROUP BY
week_num
but what I am getting is the forcast_date counts repeated in each column, i.e.
week_no | count_forcast | count_actual
1 4 4
2 5 5
3 2 2
Can any one please tell me the best way to formulate the query to get what I need??
Thanks
try:
SELECT weekofyear(forcast_date) AS week_forcast,
COUNT(forcast_date) AS count_forcast, t2.count_actual
FROM
t t1 LEFT JOIN (
SELECT weekofyear(actual_date) AS week_actual,
COUNT(forcast_date) AS count_actual
FROM t
GROUP BY weekOfYear(actual_date)
) AS t2 ON weekofyear(forcast_date)=week_actual
GROUP BY
weekofyear(forcast_date), t2.count_actual
sqlFiddle
You have to write about 30 (your date columns) left join, and the requirement is that your first date column shouldn'd have empty week (with a count of 0) or the joins will miss.
Try:
SELECT WeekInYear, ForecastCount, ActualCount
FROM ( SELECT A.WeekInYear, A.ForecastCount, B.ActualCount FROM (
SELECT weekofyear(forecast_date) as WeekInYear,
COUNT(forecast_date) as ForecastCount, 0 as ActualCount
FROM TableWeeks
GROUP BY weekofyear(forecast_date)
) A
INNER JOIN
( SELECT * FROM
(
SELECT weekofyear(forecast_date) as WeekInYear,
0 as ForecastCount, COUNT(actual_date) as ActualCount
FROM TableWeeks
GROUP BY weekofyear(actual_date)
) ActualTable ) B
ON A.WeekInYear = B.WeekInYear)
AllTable
GROUP BY WeekInYear;
Here's my Fiddle Demo
Just in case someone else comes along with the same question:
Instead of trying to use some amazing query, I ended up creating an array of date_columns_names and a loop in the program that was calling this query, and for each date_column_name, performing teh asme query. It is a bit slower, but it does work
I have the following query:
SELECT a.feeder_id, b.feeder_pr
FROM authors_article_feeders a
LEFT JOIN feeders b ON b.id = a.feeder_id
WHERE website_id =1
LIMIT 0 , 30
which results in:
feeder_id feeder_pr
18 2
18 2
18 2
18 2
32 6
What I need is to modify the above query so that it will manipulate this data so that the result would end up with a count of each feeder_pr, so in this case the result would be:
feeder_pr count
2 4
6 1
Any assistance is appreciated. If you have time please describe your solution so that I can learn from it while I'm at it.
Everything I've tried has ended in inaccurate results, usually with just one row instead of the expected 2.
You just need to add a GROUP BY And, you would not even need the joins
SELECT b.feeder_pr, COUNT(b.feeder_pr)
FROM feeders b
GROUP BY b.feeder_pr
SELECT b.feeder_pr, count(a.feeder_id) as count
FROM authors_article_feeders a
LEFT JOIN feeders b ON b.id = a.feeder_id
WHERE website_id =1
GROUP BY 1