I am new to MySQL. I have some code below which works to extract the year from a datefield, but it brings back all years from the table, ie 2011, 2012, 2013, where as I only want 2013. This is the basic query that works for the years:
SELECT EXTRACT(YEAR FROM startDate) FROM events_events where EventOwnerId = 206
This is my query where I tried to create an alias and return only 2013 years but it doesn't work:
SELECT EXTRACT(YEAR FROM startDate) as d_year
FROM events_events
where EventOwnerId = 206 AND d_year = 2013
As documented under Problems with Column Aliases:
Standard SQL disallows references to column aliases in a WHERE clause. This restriction is imposed because when the WHERE clause is evaluated, the column value may not yet have been determined.
You could repeat the EXTRACT() function within your WHERE clause:
SELECT EXTRACT(YEAR FROM startDate) AS d_year
FROM events_events
WHERE EventOwnerId = 206
AND EXTRACT(YEAR FROM startDate) = 2013
However this is not particularly efficient, as MySQL must calculate the result of the function for every record (which necessitates a full table scan). If an index on startDate is to be used, it would be better to filter for dates within the desired range:
SELECT EXTRACT(YEAR FROM startDate) AS d_year
FROM events_events
WHERE EventOwnerId = 206
AND startDate >= '2013-01-01'
AND startDate < '2014-01-01'
This should work
SELECT EXTRACT(YEAR FROM startDate) as d_year
FROM events_events
where EventOwnerId = 206 AND EXTRACT(YEAR from startDate) = 2013
Related
According to this Kaggle exercise on Task 5 (Write the query):
https://www.kaggle.com/code/setthawutkulsrisuwan/exercise-as-with
I answered 2 ways:
Query with WHERE EXTRACT() to get year and month and the answer is
INCORRECT.:
WITH RelevantRides AS
(
SELECT EXTRACT(HOUR from trip_start_timestamp) as hour_of_day, trip_seconds, trip_miles
FROM `bigquery-public-data.chicago_taxi_trips.taxi_trips`
WHERE EXTRACT(YEAR from trip_start_timestamp) = 2017 AND
EXTRACT(MONTH from trip_start_timestamp) BETWEEN 1 and 6 AND
trip_seconds > 0 AND
trip_miles > 0
)
SELECT hour_of_day,
COUNT(1) as num_trips,
3600 * SUM(trip_miles) / SUM(trip_seconds) as avg_mph
FROM RelevantRides
GROUP BY hour_of_day
ORDER BY hour_of_day
Query with the direct column name to get year and month and the answer is CORRECT.:
WITH RelevantRides AS
(
SELECT EXTRACT(HOUR from trip_start_timestamp) AS hour_of_day, trip_seconds, trip_miles
FROM `bigquery-public-data.chicago_taxi_trips.taxi_trips`
WHERE trip_start_timestamp > '2017-01-01' AND
trip_start_timestamp < '2017-07-01' AND
trip_seconds > 0 AND
trip_miles > 0
)
SELECT hour_of_day,
COUNT(1) as num_trips,
3600 * SUM(trip_miles) / SUM(trip_seconds) as avg_mph
FROM RelevantRides
GROUP BY hour_of_day
ORDER BY hour_of_day
The key differences are that first one is
WHERE EXTRACT(YEAR from trip_start_timestamp) = 2017
AND EXTRACT(MONTH from trip_start_timestamp) BETWEEN 1 and 6
, and the second is
WHERE trip_start_timestamp > '2017-01-01' AND
trip_start_timestamp < '2017-07-01'
.
In my opinion, they should result the same as querying with EXTRACT() shows year of 2017 and month of 1 to 6 as same as querying with the direct column name; however, results aren't the same.
Please explain the reasons behind those.
Thank you.
You're comparing constant dates to timestamps. Constant dates are actually timestamps looking like 2022-04-07 00:00:00.
So when you want to get all records in a date range January to June you need:
WHERE trip_start_timestamp >= '2017-01-01'
AND trip_start_timestamp < '2017-07-01'
In other words you want everything on or after midnight on the first day of the range and everything up to but not including midnight on the day after the last day. In mathematical notation you want the dates in the range [2017-01-01, 2017-07-01). The beginning of the range is closed and the end is open.
Your code like this gives a correct result.
WHERE EXTRACT(YEAR from trip_start_timestamp) = 2017
AND EXTRACT(MONTH from trip_start_timestamp) BETWEEN 1 and 6
But it can't exploit an index on your trip_start_timestamp column, so it won't be efficient in production.
My current query is as such:
SELECT
CAST(COUNT(`MID`) AS UNSIGNED) AS Y,
CONCAT(
LEFT(MONTHNAME(`date`),
3),
' ',
YEAR(`date`)
) AS label
FROM
`reservations`
WHERE
`MID` = 22 AND YEAR(`date`) = YEAR(CURDATE())
GROUP BY
CONCAT(
LEFT(MONTHNAME(DATE),
3),
' ',
YEAR(`date`)
),
YEAR(DATE),
MONTH(DATE)
ORDER BY
YEAR(`date`),
MONTH(`date`) ASC
It produces the following results that we use in Google Charts to show the number of reservations per month.
The issue is we are only getting the number of times a reservation is created, not the number of days between the start date (date) and the end date (dateLast).
Y label
________________
22 Feb 2019
28 Mar 2019
15 Apr 2019
3 May 2019
5 Jun 2019
2 Jul 2019
1 Aug 2019
1 Oct 2019
2 Nov 2019
9 Dec 2019
I've been trying the following update but getting an error related to the BETWEEN operator:
SELECT
CAST(COUNT(`mid`) AS UNSIGNED BETWEEN `date` AND `dateLast`) AS D, CONCAT(
LEFT(MONTHNAME(DATE),
3), ' ', YEAR(DATE) ),
CAST(COUNT(`mid`) AS UNSIGNED) AS Y,
CONCAT(
LEFT(MONTHNAME(DATE),
3),
' ',
YEAR(DATE)
) AS label
FROM
`reservations`
WHERE
`mid` = 22 AND YEAR(DATE) = YEAR(CURDATE())
GROUP BY
CONCAT(
LEFT(MONTHNAME(DATE),
3),
' ',
YEAR(DATE)
),
YEAR(DATE),
MONTH(DATE)
ORDER BY
YEAR(DATE),
MONTH(DATE) ASC
MySQL said: Documentation
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BETWEEN date AND dateLast) AS D, CONCAT(LEFT(MONTHNAME(DATE),' at line 2
The goal is to get a SUM for all days reserved between AND including date to dateLast Note: dateLast is not counted as it is the Checkout date. Maybe this is too complex for a SQL query and should be handled in PHP as a series of sub-routines?
If you don't need to split the number of days of one reservation over multiple months, then you can just use SUM(DATEDIFF(dateLast, date))
select year(date) y, month(date) m, sum(datediff(dateLast, date)) c
from reservations
group by y, m
order by y, m
db-fiddle
If you want to split them, then I hope your version (MySQL 8+ or MariaDB 10.2+) supports recursive queries. In that case you can expand the date range to one row per day in the range and count them:
with recursive rcte as (
select date, dateLast
from reservations
where dateLast > date -- optional
union all
select rcte.date + interval 1 day, rcte.dateLast
from rcte
where rcte.date < rcte.dateLast - interval 1 day
)
select year(date) y, month(date) m, count(*) c
from rcte
group by y,m
order by y,m
db-fiddle
SQL can definitely handle this. Use the DATEDIFF function
https://www.w3schools.com/sql/func_mysql_datediff.asp
I would like to select all records before 2014-03-22 date:
where date < 2014-03-22 // what I need
but below code doesn't see 2013 year's records :
SELECT * FROM `tractions` WHERE YEAR(date) <= 2014 AND MONTH(date) <= 3 and DAY(date) <= 22 and succ = 1
Is there anything wrong with:
SELECT * FROM tractions
WHERE date < '2014-03-22' -- place the date, correctly formatted, in quotes
Since this comparison doesn't use any functions, it will also allow you to use any indices setup on the date column.
I am using sql to write up a query in which I am trying to choose records that have their date_from column (of type date/time) that satisfy these conditions:
it can be any year
months are june, july, august and september
AND IF IT IS JUNE, IT SHOULD CONSIDER FROM THE 15th JUNE ONWARDS
Here's what i've tried ..
Select name, surname
FROM employees emp
where month(emp.date_from) IN ('06' , '07' , '08', '09')
I have also tried using CASE but failed. Any help please?
WHERE MONTH(emp.date_from) IN (7,8,9)
OR (MONTH(emp.date_from) = 6 AND DAY(emp.date_from) >= 15);
UPDATE
Or as dates are treated as strings in MySQL
WHERE RIGHT(emp.date_from, 5) BETWEEN '06-15' AND '09-30';
I don't know which would perform better however.
Sqlserver 2012
SELECT
*
FROM
employees
WHERE
DateFromParts(2000,month(date_from),day(date_from))
between '2000-06-15' and '2000-09-30'
Year 2000 is chosen because it is leap year and will handle leap year issues around 2000-02-29.
SELECT firstname,
lastname,
dateofbirth
FROM patient
WHERE Day(dateofbirth) >= CASE
WHEN Month(dateofbirth) = '06' THEN 15
END
OR Month(dateofbirth) IN ( '07', '08', '09' )
ORDER BY Month(dateofbirth)
Here's the table structure and some sample data:
pID.....month.....year
27 .....3 .....2008
27 .....12 .....2012
31 .....6 .....2008
99 .....1 .....2006
42 .....1 .....2009
pID is the practiceID and month and year represent the date period they've entered data for. I need to grab the number of practices that have entered data for the first time in Oct 2012, Nov 2012, Dec 2012 and so on.
I tried the following query for Oct 2012:
SELECT *
FROM
IPIPKDIS
where
practiceID NOT IN (
SELECT practiceID
from
IPIPKDIS
where
year < 2012 and month < 10
)
and year = 2012
and month = 10
and measureCatRecID = 2
ORDER BY year, month;
but it's grabbing months and year less than 10/2012.
If I run the queries isolated (not as subquery) they both work fine.
Any ideas?
This summary query will yield the first (smallest) date in the table for each value of practiceID.
SELECT practiceID,
MIN(STR_TO_DATE( CONCAT(year, ' ', month), '%Y %m')) first_date
FROM IPIPKDIS
GROUP BY practiceID
If you want to retrieve then the whole row for the first reported month, you'd do a nested query like this:
SELECT *
FROM IPIPKDIS I
JOIN (
SELECT practiceID,
MIN(STR_TO_DATE( CONCAT(year, ' ', month), '%Y %m')) first_date
FROM IPIPKDIS
GROUP BY practiceID
) first ON ( first.practiceID = I.practiceID
AND STR_TO_DATE( CONCAT(I.year, ' ', I.month), '%Y %m') = first.first_date)
The trick to the second query is to use the JOIN to extract just the first-month rows from your table. We use date arithmetic to do the date comparisons.