I'm using DAYOFWEEK() function in MySQL which returns 1 for sunday. But in my country the week starts with monday, not sunday. Is there any chance to get dayofweek from MySQL formated like: (1 - Monday, 2 - Tuesday, ...) ?
Use WEEKDAY() instead of DAYOFWEEK(), it begins on Monday.
If you need to start at index 1, use or WEEKDAY() + 1.
Try to use the WEEKDAY() function.
Returns the weekday index for date (0 = Monday, 1 = Tuesday, … 6 =
Sunday).
How about subtracting one and changing Sunday
IF(DAYOFWEEK() = 1, 7, DAYOFWEEK() - 1)
Of course you would have to do this for every query.
You can easily use the MODE argument:
MySQL :: MySQL 5.5 Reference Manual :: 12.7 Date and Time Functions
If the mode argument is omitted, the value of the default_week_format system variable is used:
MySQL :: MySQL 5.1 Reference Manual :: 5.1.4 Server System Variables
Could write a udf and take a value to tell it which day of the week should be 1 would look like this (drawing on answer from John to use MOD instead of CASE):
DROP FUNCTION IF EXISTS `reporting`.`udfDayOfWeek`;
DELIMITER |
CREATE FUNCTION `reporting`.`udfDayOfWeek` (
_date DATETIME,
_firstDay TINYINT
) RETURNS tinyint(4)
FUNCTION_BLOCK: BEGIN
DECLARE _dayOfWeek, _offset TINYINT;
SET _offset = 8 - _firstDay;
SET _dayOfWeek = (DAYOFWEEK(_date) + _offset) MOD 7;
IF _dayOfWeek = 0 THEN
SET _dayOfWeek = 7;
END IF;
RETURN _dayOfWeek;
END FUNCTION_BLOCK
To call this function to give you the current day of week value when your week starts on a Tuesday for instance, you'd call:
SELECT udfDayOfWeek(NOW(), 3);
Nice thing about having it as a udf is you could also call it on a result set field like this:
SELECT
udfDayOfWeek(p.SignupDate, 3) AS SignupDayOfWeek,
p.FirstName,
p.LastName
FROM Profile p;
Related
I am creating a time series of intraday (1 minute interval) time series. I have the variables date YYYYMMDD and time HH:MM:SS and would like to create the datetime YYYYMMDDTHH:MM:SS (or whatever format is not too important).
When looking at the output (just sample dates):
Date Time Datetime
20000101 9:30:00 1960-01-01T09:30:00
20000101 9:31:00 2000-01-01T09:31:00
.
.
.
20000102 9:30:00 1960-01-01T09:30:00
20000102 9:31:00 2000-01-02T09:31:00
SO whenever time is 9:30:00 the concatenation via dhms(date, 0, 0, time) gives me the wrong value.
My code actually picks stock prices in certain interval from higher frequency data:
data xtemp2;
set _v_&tables;
by symbol date time;
format datetime e8601dt. itime rtime time12.;
if first.symbol = 1 or first.date = 1 then do;
/* Initialize time and price when new symbol or date starts; */
rtime = time;
iprice = bid;
oprice = ofr;
itime = &start_time;
datetime = time;
end;
if time >= itime then do;
output;
itime = itime + &interval_seconds;
do while(time >= itime);
output;
itime = itime + &interval_seconds;
end;
end;
rtime = time;
iprice = bid;
oprice = ofr;
datetime = dhms(date, 0,0,itime);
retain itime datetime iprice oprice;
run;
Is it something in my code? because looking at the distinct date and time variable shows the correct date.
I wanted to combine these because I have a time series for each stock and would like to match merge them which - if I understand correctly - requires one unique id that could be my datetime variable.
The issue seems to be with this piece of conditional logic:
if first.symbol = 1 or first.date = 1 then do;
This means that the first instance of those by groups will execute datetime = time; instead of datetime = dhms(date, 0,0,itime); (presuming time >= itime is true).
I suggest replacing datetime = time; with datetime = dhms(date, 0,0,itime); in the first instance.
I'm looking to calculate the start date of the last quarter based on the current date.
Where
Q1 = Jan-Mar
Q2 = Apr-Jun
Q3 = Jul-Sep
Q4 = Oct-Dec
Hence, if the current date is 8th Jan 2018, the function would return the date 1st Oct 2017.
I have written the following code, however, this seems clunky and inelegant, and I have a feeling that there may be a better way to write it (for example, using dateadd).
Function LMLastQuarterStart() As Date
Dim mo As Integer
Dim yr As Integer: yr = Year(Date)
Select Case Month(Date)
Case 1 To 3: mo = 10: yr = yr - 1
Case 4 To 6: mo = 1
Case 7 To 9: mo = 4
Case Else: mo = 7
End Select
LMLastQuarterStart = DateSerial(yr, mo, 1)
End Function
I would appreciate any advice/suggestions offered, thanks.
The function you're looking for, with the DateAdd, is the following:
Public Function LastQuarter(theDate As Date) As Date
LastQuarter = DateAdd("q", DatePart("q", theDate) - 2, DateSerial(Year(theDate), 1, 1))
End Function
Explanation:
DateSerial(Year(theDate), 1, 1)) returns the first quarter of the current year.
DateAdd("q", DatePart("q", theDate), ThatDate) adds the current quarter, returning the next quarter (e.g. quarter 1 -> quarter 2). So the -2 substracts two quarters.
About clunkyness: this function may be shorter and possibly include less operations, but it's harder to understand. That may or may not be relevant.
And about parameters: I have made it take a date, to both make it easy to test and to let you keep it variable. You can do with that what you will.
Thanks to Gustav for making the suggestion to use DatePart instead of Format
My task is to get the records between 2fromdate and todate(given as a input parameters).
i am not able to use between operator for 2 input parameters...
My query as follows...
DELIMITER $$
CREATE DEFINER=`testrunner`#`%` PROCEDURE `usp_GetAllTranasactions`(pFromDate nvarchar(30),pToDate nvarchar(30),pstatus int)
BEGIN
select
ST.UserID,U.Username,
ST.SubscriptionID,
ST.DateOfSubscription,
SM.SubType,
SM.Details,
ST.Amount,
ST.EndDate,
ST.Status
from tr_t_subscriptiontransactions ST
Join tr_m_users U on U.UserID=ST.UserID
join tr_m_subscription SM on SM.SubscriptionID=ST.SubscriptionID
where **ST.DateOfSubscription between (pFromDate and pToDate) and ST.EndDate
between(pFromDate and pToDate) and ST.Status=pstatus;**
END if;
END
here i don't know how to use between parameters..plz help me..i want to retrive record between fromdate and todate..hope u understand..
Let us assume you want all transactions for the month of June 2014
In your user interface the parameter values are:
from_date = 2014-06-01
to_date = 2014-06-30
But you will evaluate against a transaction date & time. How do you ensure that absolutely every transactions on June 30 - right up to midnight - is included in the results?
Here is how: use 2014-07-01 instead of 2014-06-30, and here is what the query would look like - which does NOT use between!
SELECT
ST.UserID
, U.Username
, ST.SubscriptionID
, ST.DateOfSubscription
, SM.SubType
, SM.Details
, ST.Amount
, ST.EndDate
, ST.Status
FROM tr_t_subscriptiontransactions ST
JOIN tr_m_users U
ON U.UserID = ST.UserID
JOIN tr_m_subscription SM
ON SM.SubscriptionID = ST.SubscriptionID
WHERE (ST.DateOfSubscription >= pFromDate AND ST.DateOfSubscription < pToDate + 1)
AND (ST.EndDate >= pFromDate AND ST.EndDate < pToDate + 1)
AND ST.Status = pstatus
;
AVOID between for date ranges because it INCLUDES both the lower and upper boundary values.
... equivalent to the expression (min <= expr AND expr <= max)
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_between
What this can lead to is an "anti-pattern" which look like this:
where dt_field between '2014-06-01 00:00:00' and '2014-06-30 23:59:59'
but there are time units smaller than one second, so that approach is imperfect. Don't attempt to overcome the deficiencies of between by adjusting the upper value this way. The simple and more accurate approach is to use >= and < adjusting the upper value by one whole time unit (usually the next day).
Need SQL logic
If i enter sys date as 15th it has to fetch the values from 1-15th.
if i enter date as following month 2nd it has to fetch from 15th to
2nd.
Example
Sys date April 15th - April 1 to April 15th date values needs to be fetch.
Sys date May 2nd - April 15th to May 2nd date values needs to be fetch.
Please suggest
So as a general methodology you'd need a function to return the day number in the month, and two case statements to each return a particular date as a boundary. Date arithmetic is used to convert the system date to the upper and lower boundaries required, so on Oracle you'd use Trunc(sysdate,'mm') and add_months(...,n) and add days on as integers.
Date functions are here: http://docs.oracle.com/cd/B28359_01/server.111/b28286/functions001.htm
Can't help you with MySQL functions -- doubtless they're documented somewhere.
you'll end up with ...
date_col > case <function on sysdate>
when < 15 then <function for lower bound case 1>
when < 15 then <function for lower bound case 2>
end and
date_col < case <function on sysdate>
when < 15 then <function for upper bound case 1>
when < 15 then <function for upper bound case 2>
end and
I would recommend using DAYOFWEEK() and MONTH() functions to determine the start and end dates of the query.
SET #day = DAYOFMONTH(<date entered>)
SET #month = MONTH(<date entered>)
IF #month > MONTH(NOW()) AND #day = 2 THEN
SET #start_date = DATE_SUB(<date entered>, INTERVAL 1 MONTH) + INTERVAL 13 DAY
SET #end_date = <date entered>
ELSEIF #month = MONTH(NOW()) AND #day = 15 THEN
SET #start_date = DATE_SUB(<date entered>, INTERVAL 14 DAY)
SET #end_date = <date entered>
END IF;
SELECT * FROM myTable WHERE myDate BETWEEN #start_date AND #end_date
I am using MySQL to make a report showing the number of hours billed for a particular date range and project. The complexity is that the date range is variable for each project (different start month and start day). This information is coming from a value in another database/table.
I have the following UDF in MySQL:
DELIMITER //
CREATE FUNCTION TimeLeft(startday INT, today INT) RETURNS INT
DETERMINISTIC
BEGIN
DECLARE s INT;
IF startday < today THEN SET s = 0;
ELSE SET s = 1;
END IF;
RETURN s;
END //
DELIMITER;
I use that function in the following query, which is supposed to take the value returned in the TimeLeft function to determine the values for the start month (month(curdate())-#xx) and start day (#yy) for each project to calculate the hours:
AND time_records.record_date >= concat('2012/', month(curdate())-#xx , '/' , #yy)
Here's how I am setting the values for #xx and #yy:
SET #xx = 0; #this is the value that we will use to manipulate the month for the date range
SET #yy = 0;
#yy:= SELECT start_day_of_month FROM dashboard.client; #this doesn't seem to work
SELECT #xx:= TimeLeft(#yy,dayofmonth(curdate()));
I am getting some issues:
#yy is not getting the value - possibly my syntax is wrong?
The variables are set at the top of the code, so they are not getting changed for each project as they should be (there should be a different #xx and #yy for each project since each one has a different start and end date).
Here's the full query:
#below is where I assign the variables
SET #xx = 0; #this is the value that we will use to manipulate the month for the date range
SET #yy = 0;
#yy:= SELECT start_day_of_month FROM dashboard.client; #this doesn't seem to work
SELECT #xx:= TimeLeft(#yy,dayofmonth(curdate()));
# below is the MySQL query that is meant to use the variables assigned above
SELECT X.expr1 AS 'Project Name', #monthly_hours - SUM(X.expr2) AS 'Hours Billed
FROM
(SELECT
projects.name AS expr1
, sum(time_records.value) AS expr2
FROM project_objects
INNER JOIN projects
ON projects.id = project_objects.project_id
INNER JOIN time_records
ON time_records.parent_id = project_objects.id
WHERE time_records.parent_type = 'Task'
AND time_records.record_date >= concat('2012/', month(curdate())-#xx , '/' , #yy)
AND time_records.record_date <= curdate()
GROUP BY projects.name
UNION
SELECT
projects.name AS expr1
, sum(time_records.value) as expr2
FROM projects
INNER JOIN time_records
ON projects.id = time_records.parent_id
WHERE time_records.parent_type = 'Project'
AND time_records.record_date >= concat('2012/', month(curdate())-#xx , '/' , #yy)
AND time_records.record_date <= curdate()
GROUP BY projects.name) X
GROUP BY X.expr1
I think there is some issue of where I am assigning the variables #xx and #yy. These should be done for each individual Project, so putting them up on the top is probably not the best idea. I'm also not sure if I am assigning the #yy value correctly. It's supposed to query the value of the field of a table that is in another database but it keeps throwing a syntax error on the #yy assignment to that field.
Assign value to #yy inside select:
SELECT #yy:= start_day_of_month FROM dashboard.client;