Good day every one this is my trigger code that after the user will insert a data and select a pr date it will generate a control number in the database but my problem here is when the user pick a pr_date that is 01-28-2021 and after adding record it display a value in the datatabase 202103-1 it must display a value of 202101-1
BEGIN
SET #v1 = (SELECT control_number FROM tbl_worklog where DATE_FORMAT(pr_date,'%Y%m') =DATE_FORMAT(NOW(),'%Y%m') ORDER BY id DESC LIMIT 1);
IF (#v1 is null) THEN
SET new.control_number = (CONCAT(CAST(DATE_FORMAT(NOW(),'%Y%m') as CHAR),"-1"));
ELSE
SET #v2 = (CAST(SUBSTRING_INDEX(#v1,"-",-1) as int)+1);
SET new.control_number = (CONCAT(CAST(DATE_FORMAT(NOW(),'%Y%m') as CHAR),"-",CAST(#v2 as char)));
END IF;
END
To determine the control number, you're using the formula
DATE_FORMAT(NOW(), '%Y%m')
which will look at the current date, which is why you're getting 202103 (it's currently March, the third month). You should instead use
DATE_FORMAT(pr_date, '%Y%m')
Related
How can I delete duplicate data based on the common value (Start and End)
(Time is unique key)
My table is:
Time
Data
10:24:11
Start
10:24:12
Result
10:24:13
Result
10:24:14
End
10:24:15
Start
10:24:16
Result
10:24:17
End
I want to get Data: Result in between Start and End that is with the MAX(TIME) when duplication does occur. as such
The result that I want:
Time
Data
10:24:11
Start
10:24:13
Result
10:24:14
End
10:24:15
Start
10:24:16
Result
10:24:17
End
I have tried rearranging the data, but couldn't seems to get the result that I want, Could someone give their advice on this case?
Update
I ended up not using either of the the approach suggested by #fredt and #airliquide as my version of HSQLDB doesn't support the function.
so what I did was, adding sequence and making Start = 1, Result = 2, and End = 3.
Sequence
Time
Data
Indicator
1
10:24:11
Start
1
2
10:24:12
Result
2
3
10:24:13
Result
2
4
10:24:14
End
3
5
10:24:15
Start
1
6
10:24:16
Result
2
7
10:24:17
End
3
Thereon, I make use of the indicator and sequence to get only latest Result. Such that if previous row is 2 (which is result), remove it.
The guide that I follow:
From: Is there a way to access the "previous row" value in a SELECT statement?
select t1.value - t2.value from table t1, table t2
where t1.primaryKey = t2.primaryKey - 1
Hi a first approach will be to use a lead function as folow
select hour,status from (select *,lead(status,1) over ( order by hour) as lead
from newtable)compare
where compare.lead <> status
OR lead is null
Give me what's expected using a postgres engine.
You can do this sort of thing with SQL procedures.
-- create the table with only two columns
CREATE TABLE actions (attime TIME UNIQUE, data VARCHAR(10));
-- drop the procedure if it exists
DROP PROCEDURE del_duplicates IF EXISTS;
create procedure del_duplicates() MODIFIES SQL DATA begin atomic
DECLARE last_time time(0) default null;
for_loop:
-- loop over the rows in order
FOR SELECT * FROM actions ORDER BY attime DO
-- each time 'Start' is found, clear the last_time variable
IF data = 'Start' THEN
SET last_time = NULL;
ITERATE for_loop;
END IF;
-- each time 'Result' is found, delete the row with previous time
-- if last_time is null, no row is actually deleted
IF data = 'Result' THEN
DELETE FROM actions WHERE attime = last_time;
-- then store the latest time
SET last_time = attime;
ITERATE for_loop;
END IF;
END FOR;
END
Your data must all belong to a single day, otherwise there will be strange overlaps that cannot be distinguished. It is better to use TIMESTAMP instead of TIME.
Quick background: Process equipment vendor wrote code to update DB with results of process. Data essentially is: (Order #, Result, Qty) except that the Qty is always 1, and when the batch is large, I get a lot of identical records. Vendor software update is not an option. DB update by vendor is done by calling a stored procedure.
What I want to do in the stored procedure, is if the last record for a specific Order # has identical result as the record currently being inserted, then +1 to Qty of last record (and no new record).
In my research, all examples have included the Result as a part of the Where, which would always combine like results, but my order of results is important. If 3 have result X1, 1 has result X2, and another 2 have result X1, then I need 3 records when finished:
Order Result Qty
101 X1 3
101 X2 1
101 X1 2
I also looked at using a cursor, but that seems to expect one to look through several records, and I will only be looking at one. CTE or a nested query seem possible, but I'm not clear how to achive.
In this case, I can assume that only one machine is processing 1 order, and updates for that order will have pleanty of time to complete before the next update. But ideally the solution would be atomic and able to deal with overlapping update requests.
What I am working towards, but don't know if it is the best path (#p variables are passed in, #l variables are used to store the last record):
select top(1) #lOrder = OrderCol,
#lResult = ResultCol,
#lCreateDate = CREATEDATE
from dbo.LOG
where OrderCol = #pOrder
order by CREATEDATE desc
-- make sure the record is no more than x min old, and every other passed value matches
if ( #lOrder = #pOrder
and #lResult = #pResult
and #lCreateDate > DATEADD(minute, -7, GETDATE())
)
begin
Update dbo.LOG
set [QtyCol] += #pQty
where #lOrder = OrderCol
and #lCreateDate = CREATEDATE
end
else
begin
INSERT INTO dbo.LOG
([OrderCol], [QtyCol], [ResultCol], CREATEDATE )
VALUES(#pOrder, #pQty, #pResult, GETDATE());
end
It seems you need to check to see if the update modified rows. If not then insert. In plain language the code says: "Try to update the LOG table if the order matches an order placed within the last 7 minutes. If it doesn't find a match then insert a new row with the CREATEDATE set to the current date."
select top(1) #lOrder = OrderCol,
#lResult = ResultCol,
#lCreateDate = CREATEDATE
from dbo.LOG
where OrderCol = #pOrder
order by CREATEDATE desc;
Update dbo.LOG
set [QtyCol] += #pQty
where OrderCol = #lOrder
and ResultCol = #lResult
and ResultCol = #pResult
and CREATEDATE >= dateadd(minute, -7, getdate());
if ##rowcount=0
insert INTO dbo.LOG([OrderCol], [QtyCol], [ResultCol], CREATEDATE )
VALUES(#pOrder, #pQty, #pResult, GETDATE());
I am trying to update two fields (UNIT_COST) from (LST_RECV_COST) and VEND_ITEM_NO) from same filed (VEND_ITEM_NO).
All fields in one table (PO_VEND_ITEM). The table has sequence rows sorted by date filed (LST_RECV_DAT).
I want to update the data with record in the most recent date row.
I have used the following code
UPDATE
PO_VEND_ITEM
SET
UNIT_COST = LST_RECV_COST,
VEND_ITEM_NO = VEND_ITEM_NO,
WHERE
LST_RECV_DAT = (SELECT MAX(LST_RECV_DAT)
It always get any error message. I am new to sql and do not know which code can work.
Could you advise please?
You have some syntax mistakes.
Try this.
UPDATE PO_VEND_ITEM
SET UNIT_COST = LST_RECV_COST,
VEND_ITEM_NO = VEND_ITEM_NO
WHERE LST_RECV_DAT = (SELECT MAX(LST_RECV_DAT) FROM PO_VEND_ITEM)
use below DML to update table based on max() field
update PO_VEND_ITEM
set UNIT_COST = LST_RECV_COST
from
(select max(LST_RECV_DAT) LST_RECV_DAT,
VEND_ITEM_NO from PO_VEND_ITEM
group by VEND_ITEM_NO) t1
where VEND_ITEM_NO = t1.VEND_ITEM_NO and t1.LST_RECV_DAT = LST_RECV_DAT
My first question here..!
I'm not an expert in SQL, so bear over with me please! :)
I have a web page (not created by me) which gets report data from a MSSQL database, on the web page you enter start date and end date and data are fetched in this time interval from 00:00 on start date until 23:59 on end date.
I have managed to add more queries to the SQL, but now I would like to, for certain values only to return values which were logged in the time range 00:00:00 until 04:00:00 every day in the selected time interval.
Currently values are logged once an hour, but not always consistently. So far I have made a workaround in my web page which shows the first 4 values and skips the next 20, this loops for the selected interval. This method works 98% of the time, but occasionally there are more or fewer than 24 logged values per day which can cause the shown values will be skewed one way or another.
What I would like to do is change my SQL query so that it only returns values in the time range I want (between midnight and 04:00) for every day in the selected period. I hope someone can help me achieve this or give me some hints! :)
This is the existing SQL query running with the variables which I do want all values for. There are more variables than this but I edited them out, all the Ren*Time variables is the ones I want to make a 4-hour-every-day version of.
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..#tmpValues') IS NOT NULL BEGIN DROP TABLE #tmpValues END;
CREATE TABLE #tmpValues(Id INT PRIMARY KEY IDENTITY(1,1),BatchId INT, TimePoint DATETIME, Ren1Time DECIMAL(10,2), Ren2Time DECIMAL(10,2), Ren3Time DECIMAL(10,2), RenTotTime DECIMAL(10,2));
INSERT INTO #tmpValues(BatchId)
SELECT BatchId
FROM Batch
WHERE Batch.LogTime BETWEEN <StartTime> AND <StopTime>;
CREATE UNIQUE INDEX I_BatcId ON #tmpValues(BatchId);
UPDATE #tmpValues SET
TimePoint = (SELECT LogTime FROM Batch WHERE Batch.BatchId = #tmpValues.BatchId),
Ren1Time = (SELECT SUM(_Float) FROM LogData WHERE LogData.BatchId = #tmpValues.BatchId AND LogData.TagId = 21),
Ren2Time = (SELECT SUM(_Float) FROM LogData WHERE LogData.BatchId = #tmpValues.BatchId AND LogData.TagId = 25),
Ren3Time = (SELECT SUM(_Float) FROM LogData WHERE LogData.BatchId = #tmpValues.BatchId AND LogData.TagId = 29),
RenTotTime = (SELECT SUM(_Float) FROM LogData WHERE LogData.BatchId = #tmpValues.BatchId AND (LogData.TagId = 25 OR LogData.TagId = 29 OR LogData.TagId = 33));
DECLARE
#TimePoint DATETIME,
#Ren1Time FLOAT,
#Ren2Time FLOAT,
#Ren3Time FLOAT,
#RenTotTime FLOAT;
INSERT INTO #tmpValues(TimePoint, Ren1Time, Ren2Time, Ren3Time, RenTotTime)
VALUES(#TimePoint, #Ren1Time, #Ren2Time,#Ren3Time, #RenTotTime);
SET NOCOUNT OFF;
SELECT * FROM #tmpValues;
IF OBJECT_ID('tempdb..#tmpValues') IS NOT NULL BEGIN DROP TABLE #tmpValues END;
Don't mess around with temp tables and processing every column separately. I also have no idea what you're trying to do with those variables. You declare them, never set them, then do an INSERT with them, which will just insert a row of NULL values.
Assuming that you're using SQL Server, the DATEPART function will let you get the hour of the day.
SELECT
B.BatchID,
B.LogTime AS TimePoint,
SUM(CASE WHEN B.TagId = 21 THEN _Float ELSE 0 END) AS Ren1Time,
SUM(CASE WHEN B.TagId = 25 THEN _Float ELSE 0 END) AS Ren2Time,
SUM(CASE WHEN B.TagId = 29 THEN _Float ELSE 0 END) AS Ren3Time,
SUM(CASE WHEN B.TagId IN (21, 25, 29) THEN _Float ELSE 0 END) AS RenTotTime
FROM
dbo.Batch B
INNER JOIN LogData LD ON LD.BatchId = B.BatchId
WHERE
B.LogTime BETWEEN <StartTime> AND <StopTime> AND
DATEPART(HOUR, B.LogTime) BETWEEN 0 AND 4
GROUP BY
B.BatchID,
B.TimePoint
Thank you very much for your swift reply!
I couldn't exactly get your suggestion to work, but I did solve my problem thanks to your suggestion!
Since the SQL query which should be limited to the 4 hours is used only from one webpage and there are no values in this web page which should be shown for all 24 hours, I thought I could copy the existing .SQL file to a new file and simply change the following:
WHERE Batch.LogTime BETWEEN <StartTime> AND <StopTime>;
To
WHERE Batch.LogTime BETWEEN <StartTime> AND <StopTime> AND DATEPART(HOUR, Batch.LogTime) BETWEEN 0 AND 3;
I changed the call to the .SQL file in the web page from the old to the new file and it works! Simple as that! Also changed 0 AND 4 to 0 AND 3 since I found 03:59:59 will be included, which is exactly what I want :)
I had received some really good help earlier, and I appreciate it.
I have another record selection snafu.
I have a parameter that I need to set as the end date.
I need to pull the most recent state before the end date from a table titled state_change.
I need to exclude any records from the report who are not in the required states at that period in time.
state is set currently to be state_change.new_state
( {#grouping} = "Orders" and rec_date < {?endDate} and {#state} in [0,2,5] )
OR
( {#grouping} = "Stock" and rec_date < {?endDate} and {#state} in [1,2,3,5,7] )
If I could run a SQL query to pull this information, it would probably work, but I cannot figure out how to do it.
Essentially, I need #state to be:
Select max(new_state)
From state_change
where change_time < {?endDate}
but on a per item level.
Any help would be appreciated.
You'll probably need to use a command object with a parameter for your end date, or create a parameterized stored procedure. The command object will allow you to enter all the sql you need, like joining your results with the max newState value before the end date:
select itemID, new_state, rec_date, max_newState from
(select itemID, new_state, rec_date from table) t inner join
(Select itemID, max(new_state) as max_newState
From state_change
where change_time < {?endDate}
group by itemID) mx on t.itemid = mx.itemID and t.new_state = mx.max_newState
I can't tell if your orders and stock groupings are in the same table, so I'm not sure how you need to limit your sets by the correct state values.