When the goals were scored (range) - mysql

I am trying to create a mysql query that will show when the teams score their goals during the matches. I have a table that is setup like this: clubid(int) and minute(tinyint). This what I want to achieve:
Minute 1-15 31 goals
Minute 16-30 43 goals
Minute 31-45 36 goals
Minute 46-60 51 goals
Minute 61-75 48 goals
Minute 76-90 52 goals
First I would like to do it for every team in the league and then for each team separate. This is my attempt of the query for the whole league, but unfortunaly it doesn´t work.
SELECT *,count(minute) as summary
CASE WHEN minute >= 1 AND minute <= 15 THEN '1-15'
WHEN minute >= 16 AND minute <= 30 THEN '16-30'
WHEN minute >= 31 AND minute <= 45 THEN '31-45'
WHEN minute >= 46 AND minute <= 60 THEN '46-60'
WHEN minute >= 61 AND minute <= 75 THEN '61-75'
WHEN minute >= 76 AND minute <= 90 THEN '76-90'
WHEN minute > 90 AND THEN 90+
ELSE 'no goals' END as range
FROM teamgoals
ORDER BY range asc
Thank you in advance for any help!

Please try this sqlFiddle
SELECT IFNULL(T1.summary,0) as summary,
rangeDescription.`range`
FROM ( SELECT '1-15' as `range`, 1 as rowOrder
UNION SELECT '16-30' , 2
UNION SELECT '31-45' , 3
UNION SELECT '46-60' , 4
UNION SELECT '61-75' , 5
UNION SELECT '76-90' , 6
UNION SELECT '90+' , 7
)rangeDescription
LEFT JOIN
(SELECT count(minute) as summary,
CASE WHEN minute >= 1 AND minute <= 15 THEN '1-15'
WHEN minute >= 16 AND minute <= 30 THEN '16-30'
WHEN minute >= 31 AND minute <= 45 THEN '31-45'
WHEN minute >= 46 AND minute <= 60 THEN '46-60'
WHEN minute >= 61 AND minute <= 75 THEN '61-75'
WHEN minute >= 76 AND minute <= 90 THEN '76-90'
WHEN minute > 90 THEN '90+'
ELSE 'no goals'
END as `range`
FROM
teamgoals
WHERE clubId = 1
GROUP BY `range`
)T1
ON rangeDescription.`range` = T1.`range`
ORDER BY rangeDescription.rowOrder asc

Related

SQL Select items by percentage and timeago

That was my SQL Select without the 90% Filterung under 30 Minutes.
SELECT id, name, price, pricebefore, link, imagelink, updated, site, siteid FROM items
WHERE (case when pricebefore3 is NULL then pricebefore else pricebefore3*1.5 end) >= pricebefore
AND price < pricebefore
AND isbn != -1
AND (100-(price/pricebefore)*100) > 80
ORDER BY updated DESC
LIMIT 25
OFFSET 0
It works good, but i have the problem that items over 90% must be 30 Minutes old.
SELECT id, name, price, pricebefore, link, imagelink, updated, site, siteid FROM items
WHERE (case when pricebefore3 is NULL then pricebefore else pricebefore3*1.5 end) >= pricebefore
AND price < pricebefore
AND isbn != -1
AND (100-(price/pricebefore)*100) > 80
AND ((100-(price/pricebefore)*100) > 90 AND updated < NOW() - INTERVAL 30 MINUTE)
ORDER BY updated DESC
LIMIT 25
OFFSET 0
So i tried this one. But that gives me only items over 90%...
I need all items (also over 90%) but if there is an item OVER 90% it must be 30 minutes old. Under 90% it can be also 1 sec old... but over 90% i only need items over 30 minutes old.
So result gives me all items, but if there are items over 90% i just want items who are older than 30 minutes (just for the 90%+)
You need OR as follows:
.....
.....
( ((100-(price/pricebefore)*100) > 80 and (100-(price/pricebefore)*100) < 90)
OR
((100-(price/pricebefore)*100) > 90 AND updated < NOW() - INTERVAL 30 MINUTE) )
.....
.....
You can replace these conditions:
AND (100-(price/pricebefore)*100) > 80
AND ((100-(price/pricebefore)*100) > 90 AND updated < NOW() - INTERVAL 30 MINUTE)
with this CASE expression:
AND 1 = CASE
WHEN (100-price/pricebefore*100) > 90 THEN updated < NOW() - INTERVAL 30 MINUTE
ELSE (100-price/pricebefore*100) > 80
END

Mysql - get results from complex criteria

I have database with statistics over a number of websites and I'm currently having an issue with a rather complex query that I have no idea how to do (or if it's even possible).
I have 2 tables: websites and visits. The former is a list of all websites and their properties, while the former is a list of each user's visit on a specific website.
The program I'm making is supposed to fetch websites that need to be "scanned". The interval between each scan for each site depends on the websites total number of visits for the last 30 days. Here is a table with the intended scan-interval:
The tables have the following structure:
Websites
Visits
What I want is a query that returns the websites that are either at or past their individual update deadline (can be seen from the last_scanned column).
Is this easily doable in a single query?
Here's something you can try:
SELECT main.*
FROM (
SELECT
w.web_id,
w.url,
w.last_scanned,
(SELECT COUNT(*)
FROM visits v
WHERE v.web_id = w.web_id
AND TIMESTAMPDIFF(DAY,v.added_on, NOW()) <=30
) AS visit_count,
TIMESTAMPDIFF(HOUR,w.last_scanned, NOW()) AS hrs_since_update
FROM websites w
) main
WHERE
(CASE
WHEN visit_count >= 0 AND visit_count <= 10 AND hrs_since_update >= 4320 THEN 1
WHEN visit_count >= 11 AND visit_count <= 100 AND hrs_since_update >= 2160 THEN 1
WHEN visit_count >= 101 AND visit_count <= 500 AND hrs_since_update >= 1080 THEN 1
WHEN visit_count >= 501 AND visit_count <= 1000 AND hrs_since_update >= 720 THEN 1
WHEN visit_count >= 1001 AND visit_count <= 2000 AND hrs_since_update >= 360 THEN 1
WHEN visit_count >= 2001 AND visit_count <= 5000 AND hrs_since_update >= 168 THEN 1
WHEN visit_count >= 5001 AND visit_count <= 10000 AND hrs_since_update >= 72 THEN 1
WHEN visit_count >= 10001 AND hrs_since_update >= 24 THEN 1
ELSE 0
END) = 1;
Here's the fiddle demo: http://sqlfiddle.com/#!9/1f671/1
First, I would make a subquery to get the visit counts from the visits table for each distinct web_id. Then, LEFT OUTER JOIN the websites table to this subquery. You can then query the result for each possible condition in your visits-to-update-frequency table, like so:
SELECT websites.* FROM websites
LEFT OUTER JOIN (
SELECT visits.web_id, COUNT(*) AS visits_count FROM visits GROUP BY visits.web_id
) v ON v.web_id = websites.web_id
WHERE
(v.visits_count <= 10 AND websites.last_scanned <= DATE_SUB(NOW(), INTERVAL 4320 HOUR)) OR
(v.visits_count BETWEEN 11 AND 100 AND websites.last_scanned <= DATE_SUB(NOW(), INTERVAL 2160 HOUR)) OR
(v.visits_count BETWEEN 101 AND 500 AND websites.last_scanned <= DATE_SUB(NOW(), INTERVAL 1080 HOUR)) OR
(v.visits_count BETWEEN 501 AND 1000 AND websites.last_scanned <= DATE_SUB(NOW(), INTERVAL 720 HOUR)) OR
(v.visits_count BETWEEN 1001 AND 2000 AND websites.last_scanned <= DATE_SUB(NOW(), INTERVAL 360 HOUR)) OR
(v.visits_count BETWEEN 2001 AND 5000 AND websites.last_scanned <= DATE_SUB(NOW(), INTERVAL 168 HOUR)) OR
(v.visits_count BETWEEN 5001 AND 10000 AND websites.last_scanned <= DATE_SUB(NOW(), INTERVAL 72 HOUR)) OR
(v.visits_count > 10000 AND websites.last_scanned <= DATE_SUB(NOW(), INTERVAL 24 HOUR));
Just an improvment on #morgb query, using a table for visit count ranges
SQL FIDDLE DEMO
create table visitCount (
`min` bigint(20),
`max` bigint(20),
`frequency` bigint(20)
);
SELECT main.*
FROM (
SELECT
w.web_id,
w.url,
w.last_scanned,
(SELECT COUNT(*)
FROM visits v
WHERE v.web_id = w.web_id
AND TIMESTAMPDIFF(DAY,v.added_on, NOW()) <=30
) AS visit_count,
TIMESTAMPDIFF(HOUR,w.last_scanned, NOW()) AS hrs_since_update
FROM websites w
) main inner join
visitCount v on visit_count between v.min and v.max
WHERE
main.hrs_since_update > v.frequency

Percentage change from previous row when multiple rows have the same date?

I have a query that calculates ratios and returns them for each hour and server on a given day:
SELECT a.day,
a.hour,
Sum(a.gemspurchased),
Sum(b.gems),
Sum(b.shadowgems),
( Sum(b.gems) / Sum(a.gemspurchased) ) AS GemRatio,
( Sum(b.shadowgems) / Sum(a.gemspurchased) ) AS ShadowGemRatio
FROM (SELECT Date(Date_sub(createddate, INTERVAL 7 hour)) AS day,
Hour(Date_sub(createddate, INTERVAL 7 hour)) AS hour,
serverid,
Sum(gems) AS GemsPurchased
FROM dollartransactions
WHERE Date(Date_sub(createddate, INTERVAL 7 hour)) BETWEEN
Curdate() - INTERVAL 14 day AND Curdate()
GROUP BY 1,
2,
3) a,
/*Gems recorded from DollarTransactions Table after purchasing gem package*/
(SELECT Date(Date_sub(createddate, INTERVAL 7 hour)) AS day,
Hour(Date_sub(createddate, INTERVAL 7 hour)) AS hour,
serverid,
Sum(acceptedamount) AS Gems,
Sum(acceptedshadowamount) AS ShadowGems
FROM gemtransactions
WHERE Date(Date_sub(createddate, INTERVAL 7 hour)) BETWEEN
Curdate() - INTERVAL 14 day AND Curdate()
AND transactiontype IN ( 990, 2 )
AND fullfilled = 1
AND gemtransactionid >= 130000000
GROUP BY 1,
2,
3) b
/*Gems & Shadow Gems spent, recorded from GemTransactions Table */
WHERE a.day = b.day
AND a.serverid = b.serverid
GROUP BY 1,
2
This code returns the component parts of the ratios, as well as the ratios themselves (which are sometimes null):
day hour sum(a.GemsPurchased) sum(b.Gems) sum(b.ShadowGems) GemRatio ShadowGemRatio
9/5/2014 0 472875 465499 60766 0.9844 0.1285
9/5/2014 1 350960 371092 45408 1.0574 0.1294
9/5/2014 2 472985 509618 58329 1.0775 0.1233
9/5/2014 3 1023905 629310 71017 0.6146 0.0694
9/5/2014 4 1273170 628697 74896 0.4938 0.0588
9/5/2014 5 998920 637709 64145 0.6384 0.0642
9/5/2014 6 876470 651451 68977 0.7433 0.0787
9/5/2014 7 669100 667217 81599 0.9972 0.122
What I'd like to do is create an 8th and 9th column which calculate the % change from previous row for both GemRatio and ShadowGemRatio. I've seen other threads here on how to do this for specific queries, but I couldn't get it to work for my particular MySQL query...
Ok first create a view for that query. Let's call it v1:
CREATE VIEW v1 AS SELECT YOUR QUERY HERE;
Now here is the query to have the ratios. I assumed a day has 24 hours. The first row ratio change will be zero.
select now.*,
CASE
WHEN yesterday.gemRatio is null THEN 0
ELSE 100*(now.gemRatio-yesterday.gemRatio)/yesterday.gemRatio
END as gemChange,
CASE
WHEN yesterday.ShadowGemRatio is null THEN 0
ELSE 100*(now.ShadowGemRatio-yesterday.ShadowGemRatio)/yesterday.ShadowGemRatio
END as shadowGemChange
from v1 now left outer join v1 yesterday on
((now.day = yesterday.day && now.hour = yesterday.hour+1) ||
(DATEDIFF(now.day,yesterday.day) = 1 && now.hour = 0 && yesterday.hour=23))

mysql query to average values every hour

The following query grabs the temperature, outside temperature, ph and total suspended solids from my aquarium database and displays it in 1 table shown below. each of the values is stored in its own table and is being logged every minute.
I would like to change the query below to be able to get the average value for each hour instead of displaying the value stored in the database at x hour:00:00.
Please help
SELECT DATE_FORMAT(timeTable.minuteTime, '%Y-%m-%d %k:%i') time,
oT2.temperature temperature,
T2.temperature temp,
S2.solids solids,
P2.Ph Ph
FROM
(
SELECT minuteTime.minuteTime minuteTime,
( SELECT MAX(time) FROM outside_temperature WHERE time <= minuteTime.minuteTime AND time >= NOW() - INTERVAL 1 DAY) otempTime,
( SELECT MAX(time) FROM temperature1 WHERE time <= minuteTime.minuteTime AND time >= NOW() - INTERVAL 1 DAY) tempTime,
( SELECT MAX(time) FROM Ph WHERE time <= minuteTime.minuteTime AND time >= NOW() - INTERVAL 1 DAY) phTime,
( SELECT MAX(time) FROM solids WHERE time <= minuteTime.minuteTime AND time >= NOW() - INTERVAL 1 DAY) solidsTime
FROM
(
SELECT DATE(time) + INTERVAL (HOUR(time) DIV 2 * 2) HOUR minuteTime
FROM Ph
WHERE time >= NOW() - INTERVAL 1 DAY AND time <= NOW()
UNION SELECT DATE(time) + INTERVAL (HOUR(time) DIV 2 * 2) HOUR
FROM solids
WHERE time >= NOW() - INTERVAL 1 DAY AND time <= NOW()
UNION SELECT DATE(time) + INTERVAL (HOUR(time) DIV 2 * 2) HOUR
FROM outside_temperature
WHERE time >= NOW() - INTERVAL 1 DAY AND time <= NOW()
UNION SELECT DATE(time) + INTERVAL (HOUR(time) DIV 2 * 2) HOUR
FROM temperature1
WHERE time >= NOW() - INTERVAL 1 DAY AND time <= NOW()
GROUP BY 1
) minuteTime
) timeTable
LEFT JOIN outside_temperature oT2 ON oT2.time = timeTable.otempTime
LEFT JOIN temperature1 T2 ON T2.time = timeTable.tempTime
LEFT JOIN solids S2 ON S2.time = timeTable.solidsTime
LEFT JOIN Ph P2 ON P2.time = timeTable.phTime
ORDER BY minuteTime ASC
This is the result of the query
2013-04-03 22:00 27.12 26.06 139 7.54
2013-04-04 0:00 27.06 26 142 7.54
2013-04-04 2:00 26.94 26 142 7.5
2013-04-04 4:00 26.87 25.94 142 7.5
2013-04-04 6:00 26.75 25.87 141 7.58
2013-04-04 8:00 26.87 25.87 141 7.58
2013-04-04 10:00 26.87 25.87 141 7.58
2013-04-04 12:00 26.87 25.87 141 7.58
2013-04-04 14:00 26.69 25.87 144 7.54
2013-04-04 16:00 26.56 25.81 144 7.58
2013-04-04 18:00 26.5 25.75 144 7.61
2013-04-04 20:00 26.81 25.75 144 7.43
USE
SELECT DATE_FORMAT(timeTable.minuteTime, '%Y-%m-%d %k:%i') time,
AVG(oT2.temperature) temperature,
AVG(T2.temperature) temp,
AVG(S2.solids) solids,
AVG(P2.Ph) Ph
......./*YOUR QUERY
--AT THE LAST
GROUP BY DATE_FORMAT(timeTable.minuteTime, '%Y-%m-%d %k:%i')

How can I query from 2 dates ranges (mysql)

I want to pull the emails from 40 days ago and 20 days ago, each range being 1 day. This is what I have but it returns no rows.
SELECT s.*, r.email FROM sellyourcar s
INNER JOIN register r ON s.rid = r.slno
WHERE s.dt BETWEEN DATE_SUB(curdate(),INTERVAL 20 DAY) AND DATE_SUB(curdate(), INTERVAL 19 DAY) AND
s.t BETWEEN DATE_SUB(curdate(),INTERVAL 40 DAY) AND DATE_SUB(curdate(), INTERVAL 39 DAY)
You should be using an OR instead of and for your two intervals:
SELECT s.*, r.email
FROM sellyourcar s INNER JOIN register r ON s.rid = r.slno
WHERE s.dt BETWEEN DATE_SUB(curdate(),INTERVAL 20 DAY) AND DATE_SUB(curdate(), INTERVAL 19 DAY)
OR s.dt BETWEEN DATE_SUB(curdate(),INTERVAL 40 DAY) AND DATE_SUB(curdate(), INTERVAL 39 DAY)
As another note, at least in Oracle, I am not sure about in MYSQL the BETWEEN functions returns items matching the end items also. For example between 3 and 5 would also return items that were 3 and 5 and not just 4. So you may want to just to check if the date of the email is 20 or 40 days less than the current date.