Related
I am making a C# project in which I need help to generate and insert fields like below on MySQL database.
161013001
Where:
16 is Year,
10 is Month,
13 is day
and 001 is auto-increment numbers that reset each days.
Eg.
161012-001
161012-002
161012-002
161013-001
161013-002
161014-001
161014-002
161014-003
161014-004
161014-005
161015-001
please guide me how to make this that ID reset each day and start from 1 after every day.
Here both MySQL & SQL Server Implementation are added,
MySQL:
DROP TEMPORARY TABLE TempDate;
CREATE TEMPORARY TABLE TempDate(
Id VARCHAR(50),
Comments VARCHAR(50)
);
INSERT INTO TempDate(Id,Comments)
SELECT '190630-001', '1'
UNION
SELECT '190630-002', '2'
UNION
SELECT '190701-001', '1'
UNION
SELECT '190701-002', '2'
UNION
SELECT '190701-003', '3';
SET #v_ToDay = '';
SET #v_ToDay = (SELECT date_format(current_date(),'%y%m%d'));
SET #v_TotalByDay = '' ;
SET #v_TotalByDay =(
SELECT CONCAT('000',CAST(CASE WHEN COUNT(1) = 0 THEN 1 ELSE COUNT(1)+1 END as CHAR))
FROM TempDate
WHERE LEFT(Id,6) = #v_ToDay);
SELECT CONCAT(#v_ToDay, '-', CASE WHEN CHAR_LENGTH(RTRIM(#v_TotalByDay)) > 3 THEN RIGHT(#v_TotalByDay,3) ELSE #v_TotalByDay END) as NewIdColumn
SQL Server:
DECLARE #TempDate TABLE(
Id NVARCHAR(50),
Comments NVARCHAR(MAX)
)
INSERT INTO #TempDate(Id,Comments)
SELECT '190630-001', '1'
UNION
SELECT '190630-002', '2'
UNION
SELECT '190701-001', '1'
UNION
SELECT '190701-002', '2'
UNION
SELECT '190701-003', '3'
DECLARE #ToDay NVARCHAR(20) = (SELECT CONVERT(NVARCHAR(6), GETDATE(), 12))
DECLARE #TotalByDay NVARCHAR(20) = ''
SELECT #TotalByDay = '000' + CAST(CASE WHEN COUNT(1) = 0 THEN 1 ELSE COUNT(1)+1 END as NVARCHAR(20) )
FROM #TempDate
WHERE LEFT(Id,6) = #ToDay
SELECT #ToDay + '-' + CASE WHEN LEN(#TotalByDay) > 3 THEN RIGHT(#TotalByDay,3) ELSE #TotalByDay END as NewIdColumn
my situation is little more different then this question ....
i have a legacy database (it's not operational only use for reporting
purpose..)
in this DB transaction table was a auto increment tranx id column.
like 1, 2, 3 ...... but now our new report need meaningful tranx id
(yyMMDD<count of that day>) like this question. so actually i need a
select query to solve this problem.
with the help of #Khairul 's logic i solve my problem ....
i share my solution for other's help....
SELECT
trnx_id, account_id, pay_amount,counter_id, trantime, trandate
FROM(
SELECT
#id:=IF(#prev != t.trandate, #rownum:=1, #rownum:=#rownum+1)
,#prev:=t.trandate
,CONCAT(
SUBSTR(YEAR(t.`trandate`),3) -- year
,IF(LENGTH(MONTH(t.`trandate`))=1,CONCAT('0',MONTH(t.`trandate`)),MONTH(t.`trandate`)) -- month
,IF(LENGTH(DAY(t.`trandate`))=1,CONCAT('0',DAY(t.`trandate`)),DAY(t.`trandate`)) -- day
,IF(LENGTH(#id)=1,CONCAT('000',#id),IF(LENGTH(#id)=2,CONCAT('00',#id),IF(LENGTH(#id)=3,CONCAT('0',#id),#id))) -- count
) AS trnx_id
,t.*
FROM tax_info t ORDER BY t.`trandate`, t.`trantime`
) AS te
and my query result is ..........
After solving my problem i try to solve this question .......
for this i use a trigger for input auto increment custom column ...
my code is below , here my payment column has a custom tranx id ....
DELIMITER $$
DROP TRIGGER tranxidGeneration$$
CREATE
TRIGGER tranxidGeneration BEFORE INSERT ON payment
FOR EACH ROW BEGIN
DECLARE v_tranx_id_on INT;
-- count total row of that day
select IFNULL(COUNT(tranx_id),0)+1 Into v_tranx_id_on from payment where SUBSTR(tranx_id,1,6) = DATE_FORMAT(NOW(), "%y%m%d");
-- set custom generate id into tranx_id column
SET NEW.tranx_id := CONCAT(DATE_FORMAT(NOW(), "%y%m%d"),LPAD(v_tranx_id_on,4,0)) ;
END;
$$
DELIMITER ;
I'd like to write a query or stored procedure to retrieve less and less records over time from a relational database.
Think of this like populating the Google Finance stock chart: The past few days will have all ticks fit the day, and the further you go back, less and less ticks are displayed on each date. All ticks will show for today, 50% of ticks will show for one week ago, 30% for one month ago, and 10% for one year ago. Think of this like a gradient.
Is it possible to achieve this with one query? Or perhaps it would be necessary to use multiple queries? What might this look like?
Note that record ids are non-contiguous (there are gaps), but each record has a timestamp for determining order.
Also note that I am using MySQL.
Here is the structure of my table:
quotes
id
security_id
last_price
bid_price
ask_price
date
timestamp
trade_volume
cumulative_volume
average_volume
created_at
Sounds like you are looking for a constant set of records that represent the time-span. You can do so by defining a control date set.
Here's a sample query (doesn't account for weekends and holidays but that can be added):
POPULATE:
CREATE TABLE #quotes
(
id int identity(1,1)
,security_id VARCHAR(50)
,last_price FLOAT
,bid_price FLOAT
,ask_price FLOAT
,[date] DATETIME
,[timestamp] DATETIME
,trade_volume FLOAT
,cumulative_volume FLOAT
,average_volume FLOAT
,created_at DATETIME
)
DECLARE #i int
set #i = 100000
WHILE #i > 0
BEGIN
INSERT INTO #quotes (
security_id
,last_price
,bid_price
,ask_price
,[date]
,[timestamp]
,trade_volume
,cumulative_volume
,average_volume
,created_at
)
values( 'IBM US'
, 100.00 + RAND()
, 100.00 + RAND()
, 100.00 + RAND()
, DATEADD(MINUTE, -1* #i, GETDATE())
, DATEADD(MINUTE, -1* #i, GETDATE())
, 10000000.00 + RAND()*1000000.00
, 10000000.00 + RAND()*1000000.00
, 10000000.00 + RAND()*1000000.00
,getdate())
set #i= #i-1
END
You can change around the time span, but the following will give you around 1000 records that represent the set from start to finish.
DECLARE #StartDate DATETIME,
#EndDate DATETIME,
#j FLOAT,
#step FLOAT
set #StartDate = GETDATE()-20
SET #EndDAte = GETDATE()
set #j = 0.0
CREATE TABLE #TimeTable
(
IntervalDate DATETIME
)
--say you always want 1000 measures
--use the datediff value to define the step size:
select #step = DATEDIFF(MINUTE, #StartDate, #EndDate)/1000.0
WHILE #j < DATEDIFF(MINUTE, #StartDate, #EndDate)
BEGIN
INSERT #TimeTable (IntervalDate) VALUES (DATEADD(minute, #j, #StartDate))
SET #j = #j+#step
print #j
END
select security_id
,last_price
,bid_price
,ask_price
,[date]
,[timestamp]
,trade_volume
,cumulative_volume
,average_volume
,created_at
from #Quotes q
join #TimeTable t on dateadd(mi, datediff(mi, 0, q.date), 0) = dateadd(mi, datediff(mi, 0, t.IntervalDate), 0)
If I have a person's date of birth stored in a table in the form dd-mm-yyyy, and I subtract it from the current date, what format is the date returned in?
How can I use this returned format to calculate someone's age?
You can use TIMESTAMPDIFF(unit, datetime_expr1, datetime_expr2) function:
SELECT TIMESTAMPDIFF(YEAR, '1970-02-01', CURDATE()) AS age
Demo
If the value is stored as a DATETIME data type:
SELECT YEAR(CURRENT_TIMESTAMP) - YEAR(dob) - (RIGHT(CURRENT_TIMESTAMP, 5) < RIGHT(dob, 5)) as age
FROM YOUR_TABLE
Less precise when you consider leap years:
SELECT DATEDIFF(CURRENT_DATE, STR_TO_DATE(t.birthday, '%d-%m-%Y'))/365 AS ageInYears
FROM YOUR_TABLE t
SELECT TIMESTAMPDIFF (YEAR, YOUR_COLUMN, CURDATE()) FROM YOUR_TABLE AS AGE
Check the demo image below
Simple but elegant..
Use:
select *,year(curdate())-year(dob) - (right(curdate(),5) < right(dob,5)) as age from your_table
In this way, you consider even month and day of birth in order to have a more accurate age calculation.
select floor(datediff (now(), birthday)/365) as age
Simply:
DATE_FORMAT(FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(`birthDate`)), '%Y')+0 AS age
Since the question is being tagged for mysql, I have the following implementation that works for me and I hope similar alternatives would be there for other RDBMS's. Here's the sql:
select YEAR(now()) - YEAR(dob) - ( DAYOFYEAR(now()) < DAYOFYEAR(dob) ) as age
from table
where ...
Try this:
SET #birthday = CAST('1980-05-01' AS DATE);
SET #today = CURRENT_DATE();
SELECT YEAR(#today) - YEAR(#birthday) -
(CASE WHEN
MONTH(#birthday) > MONTH(#today) OR
(MONTH(#birthday) = MONTH(#today) AND DAY(#birthday) > DAY(#today))
THEN 1
ELSE 0
END);
It returns this year - birth year (how old the person will be this year after the birthday) and adjusts based on whether the person has had the birthday yet this year.
It doesn't suffer from the rounding errors of other methods presented here.
Freely adapted from here
Simply do
SELECT birthdate, (YEAR(CURDATE())-YEAR(birthdate)) AS age FROM `member`
birthdate is field name that keep birthdate name
take CURDATE() turn to year by YEAR() command
minus with YEAR() from the birthdate field
This is how to calculate the age in MySQL:
select
date_format(now(), '%Y') - date_format(date_of_birth, '%Y') -
(date_format(now(), '00-%m-%d') < date_format(date_of_birth, '00-%m-%d'))
as age from table
You can make a function to do it:
drop function if exists getIdade;
delimiter |
create function getIdade( data_nascimento datetime )
returns int
begin
declare idade int;
declare ano_atual int;
declare mes_atual int;
declare dia_atual int;
declare ano int;
declare mes int;
declare dia int;
set ano_atual = year(curdate());
set mes_atual = month( curdate());
set dia_atual = day( curdate());
set ano = year( data_nascimento );
set mes = month( data_nascimento );
set dia = day( data_nascimento );
set idade = ano_atual - ano;
if( mes > mes_atual ) then
set idade = idade - 1;
end if;
if( mes = mes_atual and dia > dia_atual ) then
set idade = idade - 1;
end if;
return idade;
end|
delimiter ;
Now, you can get the age from a date:
select getIdade('1983-09-16');
If you date is in format Y-m-d H:i:s, you can do this:
select getIdade(substring_index('1983-09-16 23:43:01', ' ', 1));
You can reuse this function anywhere ;)
I prefer use a function this way.
DELIMITER $$ DROP FUNCTION IF EXISTS `db`.`F_AGE` $$
CREATE FUNCTION `F_AGE`(in_dob datetime) RETURNS int(11)
NO SQL
BEGIN
DECLARE l_age INT;
IF DATE_FORMAT(NOW( ),'00-%m-%d') >= DATE_FORMAT(in_dob,'00-%m-%d') THEN
-- This person has had a birthday this year
SET l_age=DATE_FORMAT(NOW( ),'%Y')-DATE_FORMAT(in_dob,'%Y');
ELSE
-- Yet to have a birthday this year
SET l_age=DATE_FORMAT(NOW( ),'%Y')-DATE_FORMAT(in_dob,'%Y')-1;
END IF;
RETURN(l_age);
END $$
DELIMITER ;
now to use
SELECT F_AGE('1979-02-11') AS AGE;
OR
SELECT F_AGE(date) AS age FROM table;
There is two simple ways to do that:
select("users.birthdate",
DB::raw("FLOOR(DATEDIFF(CURRENT_DATE, STR_TO_DATE(users.birthdate, '%Y-%m-%d'))/365) AS age_way_one"),
select("users.birthdate",DB::raw("(YEAR(CURDATE())-YEAR(users.birthdate)) AS age_way_two"))
I'm doing something like this:
SELECT date_format(mydate, '%d/%m/%Y') FROM xyz;
When mydate is NULL, date_format returns 00/00/0000. This is correct, but how can I make it so that it returns NULL when the input is NULL?
SELECT IF(mydate,date_format(mydate, '%d/%m/%Y'),NULL) FROM xyz;
Source: http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html
You can wrap this into a IF-Clause, like this:
SELECT IF(mydate,DATE_FORMAT(mydate, '%d/%m/%Y'),NULL) FROM xyz;
That said, if your variable mydate is not a date value, the query in your post should return (NULL) anyway.
select case when isnull(mydate) then null else date_format(mydate, '%d/%m/%Y') end as mydate from xyz;
case
when date_format(mydate, '%d/%m/%Y') = 00/00/0000 then null
else ///
end as mydate,
I'm having the same problem as described here, unfortunately the solution does not work for MS SQL Server.
Does a similar syntax exist for MS SQL Server?
Note: my query is not as simple as in the example. I'd like to reuse DifferenceMinutes in the TooLateTime case.
DATEDIFF(MINUTE, DayOfWeekStopTime, GETDATE()) AS DifferenceMinutes,
CASE
WHEN DATEDIFF(MINUTE, DayOfWeekStopTime, GETDATE()) < 0 THEN NULL
ELSE CONVERT(varchar, GETDATE() - DayOfWeekStopTime, 108)
END AS TooLateTime
It's a little hard to tell exactly what you're trying to do, but I think this might be what you're looking for:
SELECT
DifferenceMinutes,
CASE
WHEN DifferenceMinutes < 0 THEN NULL
ELSE CONVERT(varchar, GETDATE() - DayOfWeekStopTime, 108)
END AS TooLateTime
FROM (
SELECT
DayOfWeekStopTime,
DATEDIFF(MINUTE, DayOfWeekStopTime, GETDATE()) AS DifferenceMinutes
FROM TableName
) X
You'll have to substitute your source table(s) for "TableName" in the FROM section of the inner query.
By rolling your calculated values into a nested select like this, you can refer to them by whatever name you give them in the outer query.
If you want to set variables for each of the values, you can do that as follows, but you'll need to make sure you're only returning one row from the query:
DECLARE #DifferenceMinutes int, #TooLateTime varchar(30)
SELECT
#DifferenceMinutes = DifferenceMinutes,
#TooLateTime = CASE
WHEN DifferenceMinutes < 0 THEN NULL
ELSE CONVERT(varchar, GETDATE() - DayOfWeekStopTime, 108)
END
FROM (
SELECT
DayOfWeekStopTime,
DATEDIFF(MINUTE, DayOfWeekStopTime, GETDATE()) AS DifferenceMinutes
FROM TableName
) X