SQL IF exist date by day do increment update else insert data - mysql

How can I express the below statement as a SQL query ?
IF EXISTS (SELECT * FROM expense_history
WHERE user_id = 40
AND DATE_FORMAT(expense_history.created_date , '%Y-%m-%d') = '2018-06-02'
AND camp_id='80')
UPDATE expense_history
SET clicks = clicks + 1,
amount = amount + 1
WHERE user_id = 40
AND DATE_FORMAT(expense_history.created_date, '%Y-%m-%d') = '2018-06-02'
AND camp_id = '80'
ELSE
INSERT INTO expense_history (camp_id, created_date, amount, user_id)
VALUES ('80', '2018-06-02 12:12:12', '1', '40')
END IF;
I just want to do increment clicks and amount if is set by day, else I want to add new row.

This is very tricky in MySQL. You are storing a datetime but you want the date part to be unique.
Starting in MySQL 5.7.?, you can use computed columns for the unique constraint. Here is an example:
create table expense_history (
user_id int,
camp_id int,
amount int default 0,
clicks int default 1,
. . .
created_datetime datetime, -- note I changed the name
created_date date generated always as (date(created_datetime)),
unique (user_id, camp_id, created_datetime)
);
You can then do the work as:
INSERT INTO expense_history (camp_id, created_datetime, amount, user_id)
VALUES (80, '2018-06-02 12:12:12', 1, 40)
ON DUPLICATE KEY UPDATE
amount = COALESCE(amount + 1, 1),
clicks = COALESCE(clicks + 1, 1);
Earlier versions of MySQL don't support generated columns. Nor do they support functions on unique. But you can use a trick on a prefix index on a varchar to do what you want:
create table expense_history (
user_id int,
camp_id int,
amount int default 0,
clicks int default 1,
. . .
created_datetime varchar(19),
unique (created_datetime(10))
);
This has the same effect.
Another alternative is to store the date and the time in separate columns.

I presumed your database is mysql, because of DATE_FORMAT() function(and edited your question as to be).
So, by using such a mechanism below, you can do what you want,
provided that a COMPOSITE PRIMARY KEY for camp_id, amount, user_id columns :
SET #camp_id = 80,
#amount = 1,
#user_id = 40,
#created_date = sysdate();
INSERT INTO expense_history(camp_id,created_date,amount,user_id,clicks)
VALUES(#camp_id,#created_date,#amount,#user_id,ifnull(clicks,1))
ON DUPLICATE KEY UPDATE
amount = #amount + 1,
clicks = ifnull(clicks,0)+1;
SQL Fiddle Demo

Related

Week date range

There is a table objects, which stores data on real estate objects. Me need to use a query to calculate a new field that will display the date range from Monday to Sunday, which includes the date the object was created (for example, “2020-11-16 - 2020-11-22”)
create table objects(
object_id int NOT NULL PRIMARY KEY ,
city_id int not null ,
price int ,
area_total int ,
status varchar(50) ,
class varchar(50) ,
action varchar(50) ,
date_create timestamp,
FOREIGN KEY(city_id) references avg_price_square_city(city_id)
);
Data in the table:
INSERT INTO objects (object_id, city_id, price, area_total, status, class, action, date_create)
VALUES (1, 1, 4600000, 72, 'active', 'Secondary', 'Sale', '2022-05-12 21:49:34');
INSERT INTO objects (object_id, city_id, price, area_total, status, class, action, date_create)
VALUES (2, 2, 5400000, 84, 'active', 'Secondary', 'Sale', '2022-05-19 21:49:35');
The query should display two fields: the object number and a range that includes the date it was created. How can this be done ?
P.S
I wrote this query,but he swears at the "-" sign:
SET #WeekRangeStart ='2022/05/10';
SET #WeekRangeEnd = '2022/05/17';
select object_id,#range := #WeekRangeStart '-' #WeekRangeEnd
FROM objects where #range = #WeekRangeStart and date_create between #WeekRangeStart and #WeekRangeEnd
UNION
select object_id,#range from objects where #`range` = #WeekRangeEnd;
Error:[42000][1064] 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 '#WeekRangeEnd FROM objects where #range = #WeekRangeStart and date_create betwee' at line 1
I want to receive in query:
object_id #range
1 2022/05/10 - 2022/05/17
The column #range must contain the date from the "date_create"
SET #WeekRangeStart = CAST('2022/05/10' as DATE);
SET #WeekRangeEnd = CAST('2022/05/17' as DATE);
SET #range = CONCAT(#WeekRangeStart,' - ',#WeekRangeEnd) ;
-- select #range;
select
object_id,
#range
FROM objects
where DATE(date_create) between #WeekRangeStart and #WeekRangeEnd
UNION
select object_id,#range from objects
;
Gives next result:
object_id
#range
1
2022-05-10 - 2022-05-17
2
2022-05-10 - 2022-05-17
This result is the output of the SQL part that is put after the UNION. Because date_create is not between your WeekRangeStart and WeekRangeEnd.
You should take some time, and read the UNION documentation.
The variable #range is calculated before the SQL statement, because the value is a constant.
see: DBFIDDLE
NOTE: You should try to use the same dateformat everywhere, and not mix date like '2022-05-19 21:49:35' and 2022/05/10. Use - OR use /, but do not mix them...
EDIT: After the calirification "Me need to use a query to calculate a new field that will display the date range from Monday to Sunday,...":
You probably wanted to do:
SET #WeekDate = CAST('2022/05/10' as DATETIME);
SELECT
ADDDATE(#WeekDate, -(DAYOFWEEK(#WeekDate)-1) +1) as Monday,
DATE_ADD(ADDDATE(#WeekDate, -(DAYOFWEEK(#WeekDate)-1) +9), INTERVAL -1 SECOND) as Sunday;
output:
Monday
Sunday
2022-05-09 00:00:00
2022-05-16 23:59:59

How to use validation when i use duplicate key update

When I Use duplicate key update
INSERT INTO test_table (name, age, date)
VALUES (Kevin, 20, now)
ON DUPLICATE KEY UPDATE name = VALUES(name),
age = VALUES(age),
date = VALUES(date)
I want to compare with existing value for validation
How can I do?
I have tried some method
where date < VALUES(date)
But all of method are syntax error
Thanks for reading
Try using CASE EXPRESSION :
INSERT INTO test_table (name, age, date)
VALUES (Kevin, 20, now)
ON DUPLICATE KEY
UPDATE name = CASE WHEN `date`< values(`date`) THEN VALUES(name) ELSE name end,
age= CASE WHEN `date`< values(`date`) THEN VALUES(age) ELSE age end,
`date`= CASE WHEN `date`< values(`date`) THEN VALUES(date) ELSE `date` end
INSERT INTO test_table (name, age, date)
VALUES (Kevin, 20, now)
ON DUPLICATE KEY UPDATE age = IF(`date` < values(`date`), values(age), age),
name = IF(`date` < values(`date`), values(name), name),
date = IF(`date` < values(`date`), values(date), date)

Copy datetime to same table after conversion

Very new to SQL 2 weeks in. I have date in table have added extra columns in table, copied date field to each column. Alter the dates for 6 &18 weeks from original date. I need to convert the date to uk short date & copy result to table preferably replacing existing data in the columns.
COLUMNS are REF_DATE this is original date
Six_wk
Eighteen_wk
this is the SQL so far
ALTER TABLE [Frontsheets].[dbo].[j38_spfit_op_activity_noc]
ADD
APPOINTMENT_DATE nvarchar(11),
APPOINTMENT_TIME datetime,
Six_wk datetime,
Eighteen_wk datetime
go
update [Frontsheets].[dbo].[j38_spfit_op_activity_noc] set APPOINTMENT_DATE = APPT_DTTM, Six_wk = REF_DATE, Eighteen_wk = REF_DATE, APPOINTMENT_TIME = APPT_DTTM
go
UPDATE [Frontsheets].[dbo].[j38_spfit_op_activity_noc] SET Six_wk = DATEADD( "d" , 42, REF_DATE ), Eighteen_wk = DATEADD( "d" , 126, REF_DATE )
Go
Select REF_DATE = convert(nvarchar(10),REF_DATE, 103),
Six_wk = CONVERT(varchar(10), Six_wk, 103),
Eigheen_wk = CONVERT(varchar(10), Eighteen_wk, 103)
from [Frontsheets].[dbo].[j38_spfit_op_activity_noc]
Now I cant seem to save the converted data to my table?

Increase Alphanumeric VARCHAR Entry by Value 1?

On an old project because of not thought through design I have a column which actually should be set to auto_increment, though it cannot be because it are alphanumeric entries as follows:
c01
c02
c03
(c99 would continue to c100 and more), the letter happened in the past and it would require to overhaul the system to take it out, thus I rather prefer this workaround.
Now I need a way to imitate the auto_increment functionality with the SQL statement myself, my own attempt has gotten as far as the following:
INSERT INTO tags (tag_id, tag_name, tag_description, added_by_user_id, creation_date, last_edited) VALUES (SELECT(MAX(tag_id)+1),
'Love', 'All about love', 7, now(), 0);
This one does not work as is, though the idea was to select the highest entry in the column "tag_id" and then simply increase it by the value 1.
Any ideas how to accomplish this?
By the way I am also not sure if you simply can increase an alphanumeric entry through this way, though I know it can be done, I just don't know how.
If you want to safely get the largest integer value of a tag id of the form c##.., you could use the following expression:
max( convert( substring(tag_id, 2) , unsigned integer) )
^^^ largest ^^^^^^^^^ after 'c' ^^^^^^^^^^^^^^^^ convert to positive number
Then your insert statement would look something like this:
set #newid = convert(
(select
max(convert( (substring(tag_id, 2)) , unsigned integer))+1
from tags), char(10)
);
set #newid = if(length(#newid) = 1, concat('0', #newid), #newid);
set #newid = concat('c', #newid);
INSERT INTO tags (tag_id, tag_name, tag_description, added_by_user_id,
creation_date, last_edited)
VALUES (#newid, 'Love', 'All about love', 7, now(), '2012-04-15');
Demo: http://www.sqlfiddle.com/#!2/0bd9f/1
this will increase from c01 to c02 to c03 ... to c99 to c100 to c101 ... to c999 to c1000 etc.
set #nextID = (SELECT CONCAT(SUBSTRING(`tag_id`, 1, 1), IF(CHAR_LENGTH(CAST(SUBSTRING(`tag_id`, 2)
AS UNSIGNED)) < 2, LPAD(CAST(CAST(SUBSTRING(`tag_id`, 2) AS UNSIGNED) + 1 AS CHAR), 2,
'0'), CAST(CAST(SUBSTRING(`tag_id`, 2) AS UNSIGNED) + 1 AS CHAR))) FROM `tags` ORDER BY
`tag_id` DESC LIMIT 1);
INSERT INTO tags (tag_id, tag_name, tag_description, added_by_user_id,
creation_date, last_edited) VALUES (#nextID, 'Love', 'All about love', 7, NOW(), null);

How to wirte a query for updating two tables at a time?

HI i have two tables in my database named...Requests and Balance tracker which has no relation....but i want to select data from two tables and binf it two grid...
Requests
EmpID |EmpRqsts|EmpDescription|ApproverID|ApprovedAmount|RequestPriority
1 |asdfsb |sadbfsbdf |1 |
2 |asbfd |sjkfbsd |1 |
Balance Tracker
EmpId|BalanceAmnt|LastUpdated|lastApprovedAmount
| 1 |5000 |sdfbk |
| 2 |3000 |sjbfsh |
now i want to update based on the EmpID two tables at a time...when ever amount is approved it should be updates in request table column [ApprovedAmount] and with priority...
when [ApprovedAmount] is Updated [BalanceAmnt] Balance Tracker of also should be Updated by adding the amount approved,[LastUpdated],[lastApprovedAmount] should be updated with date and time
can any one help me with the query please....
#Anil, here is an example of SQL Server 2008 code which would help you to get your goal acomplished:
DECLARE #Requests TABLE
(
EmpId int
, EmpRqsts nvarchar(50)
, EmpDescription nvarchar(250)
, ApproverID int
, ApprovedAmount money
, RequestPriority int
)
DECLARE #BalanceTracker TABLE
(
EmpId int
, BalanceAmnt money
, LastUpdated datetime
, lastApprovedAmount money
)
-- Insert data for testing
INSERT INTO #Requests VALUES
(
1
, 'Something here'
, 'Some descriptio here'
, 1
, 100
, 1
)
INSERT INTO #Requests VALUES
(
2
, 'Something here 2 '
, 'Some descriptio here 3'
, 1
, 215
, 2
)
INSERT INTO #BalanceTracker VALUES
(
1
, 5000
, GETDATE() - 3
, 310
)
INSERT INTO #BalanceTracker VALUES
(
2
, 3000
, (GETDATE() - 1)
, 98
)
-- Declare local variables
DECLARE
#NewAmount money
, #NewPriority int
, #SelectedEmpId int
-- Assing values for example
SELECT #NewAmount = 1000
, #SelectedEmpId = 1
, #NewPriority = 5
-- Get the tables values pre - updates
SELECT *
FROM #Requests
SELECT *
FROM #BalanceTracker
BEGIN TRY
-- Update the record with new ApprovedAmount and Request Priority
UPDATE #Requests
SET ApprovedAmount = #NewAmount
, RequestPriority = #NewPriority
WHERE EmpId = #SelectedEmpId
-- If no error found then update BalanceAmnt trable
IF (##ERROR = 0)
BEGIN TRY
UPDATE #BalanceTracker
SET BalanceAmnt = (BalanceAmnt + #NewAmount)
, LastUpdated = GETDATE()
, lastApprovedAmount = #NewAmount
WHERE EmpId = #SelectedEmpId
END TRY
BEGIN CATCH
PRINT N'Error found updating #BalanceTracker table: ' + ISNULL(LTRIM(STR(ERROR_NUMBER())) , N'Unknown Error' )
+ N', Message: ' + ISNULL ( ERROR_MESSAGE() , N'No Message' )
END CATCH
END TRY
BEGIN CATCH
PRINT N'Error found updating #Requests table: ' + ISNULL(LTRIM(STR(ERROR_NUMBER())) , N'Unknown Error' )
+ N', Message: ' + ISNULL ( ERROR_MESSAGE() , N'No Message' )
END CATCH
-- Get the tables values post - updates
SELECT *
FROM #Requests
SELECT *
FROM #BalanceTracker
Note 1: #Table are Variable Tables handlded by SQL Server 2008. If you're using previous version you should be able to create Temporary Table (#Table).
Note 2: data data-types may vary depending upon the SQL version you're using.
You could do this type of thing with a trigger. This way whenever you do the first update, it will automatically do the other update you specify.