SQL Change time values with delayed minutes to "previous" minute - mysql

Here's an example:
My database has several entries where the time values are:
10:00:00
10:10:00
10:20:00
...
Then sometimes there are these values where we have a 1 minute delay like:
10:20:00
10:31:00 <-
10:40:00
10:51:00 <-
And I wanted these numbers to, each, go to their respective minutes:
10:20:00
10:31:00 -> 10:30:00
10:40:00
10:51:00 -> 10:50:00
Edit: The time are sole entries, I have my date value in another column, for visualization my columns are
keyDate keyTime Sequency Value
12-03-2018 10:40:00 12 143

Please try this.
SELECT
CONVERT(TIME,CASE WHEN RIGHT(datepart(minute,BeginTime),1) = 1
THEN
CONVERT(VARCHAR(2),datepart(Hour,BeginTime)) +':'
+ CONVERT(VARCHAR(2),datepart(minute,BeginTime) - 1)
+':'
+ CONVERT(VARCHAR(2),datepart(second,BeginTime))
ELSE
CONVERT(VARCHAR(8),BeginTime)
END)
FROM #tbl
For example
Declare #tbl Table(
ArrangeId INT ,
BeginTime TIME,
EndDate NVARCHAR(50),
DeptId INT
)
INSERT INTO #tbl VALUES(1,'7:20:00','22:30',NULL)
INSERT INTO #tbl VALUES(3,'7:10:00','23:00',NULL)
INSERT INTO #tbl VALUES(2,'7:11:00','23:59',NULL)
INSERT INTO #tbl VALUES(4,'6:10:00','22:30',NULL)
INSERT INTO #tbl VALUES(4,'5:11:00','22:30',NULL)
INSERT INTO #tbl VALUES(4,'5:31:00','22:30',NULL)
SELECT
CONVERT(TIME,CASE WHEN RIGHT(datepart(minute,BeginTime),1) = 1
THEN
CONVERT(VARCHAR(2),datepart(Hour,BeginTime)) +':'
+ CONVERT(VARCHAR(2),datepart(minute,BeginTime) - 1)
+':'
+ CONVERT(VARCHAR(2),datepart(second,BeginTime))
ELSE
CONVERT(VARCHAR(8),BeginTime)
END)
FROM #tbl

Related

MySQL calculating query

I have this table, only two columns, each record stores an interest rate for a given month:
id rate
===========
199502 3.63
199503 2.60
199504 4.26
199505 4.25
... ...
201704 0.79
201705 0.93
201706 0.81
201707 0.80
201708 0.14
Based on this rates, I need to create another table of accumulated rates which similar structure, whose data is calculated as function of a YYYYMM (month/year) parameter, this way (this formula is legally mandatory):
The month given as parameter has always rate of 0 (zero)
The month immediately previous has always a rate of 1 (one)
The previous months' rates will be (one) plus the sum of rates of months between that given month and the month given as parameter.
I'll clarify this rules with this example, given parameter 201708:
SOURCE CALCULATED
id rate id rate
=========== =============
199502 3.63 199502 360.97 (1 + sum(rate(199503) to rate(201707)))
199503 2.60 199503 358.37 (1 + sum(rate(199504) to rate(201707)))
199504 4.26 199504 354.11 (1 + sum(rate(199505) to rate(201707)))
199505 4.25 199505 349.86 (1 + sum(rate(199506) to rate(201707)))
... ... ... ...
201704 0.79 201704 3.54 (1 + rate(201705) + rate(201706) + rate(201707))
201705 0.93 201705 2.61 (1 + rate(201706) + rate(201707))
201706 0.81 201706 1.80 (1 + rate(201707))
201707 0.80 201707 1.00 (per definition)
201708 0.14 201708 0.00 (per definition)
Now I've already implemented a VB.NET function that reads the source table and generates the calculated table, but this is done in runtime at each client machine:
Public Function AccumRates(targetDate As Date) As DataTable
Dim dtTarget = Rates.Clone
Dim targetId = targetDate.ToString("yyyyMM")
Dim targetIdAnt = targetDate.AddMonths(-1).ToString("yyyyMM")
For Each dr In Rates.Select("id<=" & targetId & " and id>199412")
If dr("id") = targetId Then
dtTarget.Rows.Add(dr("id"), 0)
ElseIf dr("id") = targetIdAnt Then
dtTarget.Rows.Add(dr("id"), 1)
Else
Dim intermediates =
Rates.Select("id>" & dr("id") & " and id<" & targetId).Select(
Function(ldr) New With {
.id = ldr.Field(Of Integer)("id"),
.rate = ldr.Field(Of Decimal)("rate")}
).ToArray
dtTarget.Rows.Add(
dr("id"),
1 + intermediates.Sum(
Function(i) i.rate))
End If
Next
Return dtTarget
End Function
My question is how can I put this as a query in my database so it can be used dynamically by other queries which would use these accumulated rates to update debts to any given date.
Thank you very much!
EDIT
I managed to make a query that returns the data I want, now I just don't know how to encapsulate it so that it can be called from another query passing any id as argument (here I did it using a SET ... statement):
SET #targetId=201708;
SELECT
id AS id_acum,
COALESCE(1 + (SELECT
SUM(taxa)
FROM
tableSelic AS ts
WHERE
id > id_acum AND id < #targetId
LIMIT 1),
IF(id >= #targetId, 0, 1)) AS acum
FROM
tableSelic
WHERE id>199412;
That's because I'm pretty new to MySQL, I'm used to MS-Access where parametrized queries are very straightfoward to create.
For example:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL PRIMARY KEY
,rate DECIMAL(5,2) NOT NULL
);
INSERT INTO my_table VALUES
(201704,0.79),
(201705,0.93),
(201706,0.81),
(201707,0.80),
(201708,0.14);
SELECT *
, CASE WHEN #flag IS NULL THEN #i:=1 ELSE #i:=#i+rate END i
, #flag:=1 flag
FROM my_table
, (SELECT #flag:=null,#i:=0) vars
ORDER
BY id DESC;
+--------+------+-------------+-------+------+------+
| id | rate | #flag:=null | #i:=0 | i | flag |
+--------+------+-------------+-------+------+------+
| 201708 | 0.14 | NULL | 0 | 1 | 1 |
| 201707 | 0.80 | NULL | 0 | 1.80 | 1 |
| 201706 | 0.81 | NULL | 0 | 2.61 | 1 |
| 201705 | 0.93 | NULL | 0 | 3.54 | 1 |
| 201704 | 0.79 | NULL | 0 | 4.33 | 1 |
+--------+------+-------------+-------+------+------+
5 rows in set (0.00 sec)
Ok, I made it with a function:
CREATE FUNCTION `AccumulatedRates`(start_id integer, target_id integer) RETURNS decimal(6,2)
BEGIN
DECLARE select_var decimal(6,2);
SET select_var = (
SELECT COALESCE(1 + (
SELECT SUM(rate)
FROM tableRates
WHERE id > start_id AND id < target_id LIMIT 1
), IF(id >= unto, 0, 1)) AS acum
FROM tableRates
WHERE id=start_id);
RETURN select_var;
END
And them a simple query:
SELECT *, AccumulatedRates(id,#present_id) as acum FROM tableRates;
where #present_id is passed as parameter.
Thanks to all, anyway!

Get count of columns having same value in comma separated format Sql

Hi i need a complex query
my table structure is
attribute_id value entity_id
188 48,51,94 1
188 43,22 2
188 43,22 3
188 43,22 6
190 33,11 10
190 90,61 12
190 90,61 15
I need the count of the value like
attribute_id value count
188 48 2
188 43 3
188 51 1
188 94 1
188 22 2
190 33 1
190 11 1
190 90 2
190 61 2
I have searched a lot on google to have something like this but unfortunately i didn't get any success. Please suggest me how can i achieve this .
I use a UDF for things like this. If that could work for you:
CREATE FUNCTION [dbo].[UDF_StringDelimiter]
/*********************************************************
** Takes Parameter "LIST" and transforms it for use **
** to select individual values or ranges of values. **
** **
** EX: 'This,is,a,test' = 'This' 'Is' 'A' 'Test' **
*********************************************************/
(
#LIST VARCHAR(8000)
,#DELIMITER VARCHAR(255)
)
RETURNS #TABLE TABLE
(
[RowID] INT IDENTITY
,[Value] VARCHAR(255)
)
WITH SCHEMABINDING
AS
BEGIN
DECLARE
#LISTLENGTH AS SMALLINT
,#LISTCURSOR AS SMALLINT
,#VALUE AS VARCHAR(255)
;
SELECT
#LISTLENGTH = LEN(#LIST) - LEN(REPLACE(#LIST,#DELIMITER,'')) + 1
,#LISTCURSOR = 1
,#VALUE = ''
;
WHILE #LISTCURSOR <= #LISTLENGTH
BEGIN
INSERT INTO #TABLE (Value)
SELECT
CASE
WHEN #LISTCURSOR < #LISTLENGTH
THEN SUBSTRING(#LIST,1,PATINDEX('%' + #DELIMITER + '%',#LIST) - 1)
ELSE SUBSTRING(#LIST,1,LEN(#LIST))
END
;
SET #LIST = STUFF(#LIST,1,PATINDEX('%' + #DELIMITER + '%',#LIST),'')
;
SET #LISTCURSOR = #LISTCURSOR + 1
;
END
;
RETURN
;
END
;
The UDF takes two parameters: A string to be split, and the delimiter to split by. I've been using it for all sorts of different things over the years, because sometimes you need to split by a comma, sometimes by a space, sometimes by a whole string.
Once you have that UDF, you can just do this:
DECLARE #TABLE TABLE
(
Attribute_ID INT
,Value VARCHAR(55)
,Entity_ID INT
);
INSERT INTO #TABLE VALUES (188, '48,51,94', 1);
INSERT INTO #TABLE VALUES (188, '43,22', 2);
INSERT INTO #TABLE VALUES (188, '43,22', 3);
INSERT INTO #TABLE VALUES (188, '43,22', 6);
INSERT INTO #TABLE VALUES (190, '33,11', 10);
INSERT INTO #TABLE VALUES (190, '90,61', 12);
INSERT INTO #TABLE VALUES (190, '90,61', 15);
SELECT
T1.Attribute_ID
,T2.Value
,COUNT(T2.Value) AS Counter
FROM #TABLE T1
CROSS APPLY dbo.UDF_StringDelimiter(T1.Value,',') T2
GROUP BY T1.Attribute_ID,T2.Value
ORDER BY T1.Attribute_ID ASC, Counter DESC
;
I did an ORDER BY Attribute_ID ascending and then the Counter descending so that you get each Attribute_ID with the most common repeating values first. You could change that, of course.
Returns this:
Attribute_ID Value Counter
-----------------------------------
188 43 3
188 22 3
188 94 1
188 48 1
188 51 1
190 61 2
190 90 2
190 11 1
190 33 1

Adding values from 2 rows based on conditions

I have a table as Below....
ROW gvkey datadate CQTR CYEARQ Value
1 6066 3/31/2015 0:00 1 2015 3610
2 6066 12/31/2014 0:00 4 2014 16868
3 6066 9/30/2014 0:00 3 2014 10809
4 6066 6/30/2014 0:00 2 2014 6905
5 6066 3/31/2014 0:00 1 2014 3326
I want to get the sum of Value of 3/31/2015 and 12/31/2014. Please suggest how Can I do it in MS Sql.
Are you looking for this :-
Set Nocount On;
If Object_Id('tempdb.dbo.#table') Is Not Null
Begin
Drop Table #table;
End
Create Table #table
(
Id Int Primary Key
,Col1 Int
,RDate Datetime
,Col2 Int
,RYear Int
,Col3 Int
)
Insert Into #table Values
(1,6066,'03/31/2015 0:00',1,2015,3610)
,(2,6066,'12/31/2014 0:00',4,2014,16868)
,(3,6066,'09/30/2014 0:00',3,2014,10809)
,(4,6066,'06/30/2014 0:00',2,2014,6905)
,(5,6066,'03/31/2014 0:00',1,2014,3326)
Select t.Col1
,Sum(t.Col3) As ColSum
From #table As t With (Nolock)
Where t.RDate In ('03/31/2015','12/31/2014')
Group By t.Col1

Sum until value reached zero

I have two queries.
The result of the first one is the OnHand quantity of the part in the warehouse:
PartNum OnHandQty IUM
100009 19430.00 KG
The result of the second query are transactions related to the receipts of the goods to the warehouse:
TranDate PartNum TranQty UM Dayss
2014-09-01 100009 10720.000 KG 2
2014-09-01 100009 1340.000 KG 2
2014-08-11 100009 8710.000 KG 23
2014-08-11 100009 3350.000 KG 23
2014-06-30 100009 9380.000 KG 65
Now I need to calculate OnHandQy - TranQty until it hits zero, e.g.
19430 - 10720 = 8710 --not enough
8710 - 1340 = 7370 --not enough
7370 - 8710 = -1340 --enough
As a result I need to receive a table like below:
PartNum OnHandQty IUM [0-10 Days] [11-20 Days] [over 21 Days]
100009 19430.00 KG 12060 null 8710
Any ideas how to get this result?
One idea is to use the following query.
WITH(TranDate,PartNum,TranQty,UM,Dayss) trans
AS
(
-- Your second query
)
SELECT F.PartNum
,F.OnHandQty
,F.IUM
,SUM(t0to10.TransQty) AS [0-10 Days]
,SUM(t11to20.TransQty) AS [11-20 Days]
,SUM(tover20.TransQty) AS [over 21 Days]
FROM (Your first query) AS F
JOIN trans AS t0to10 ON F.PartNum = t0to10.PartNum
AND t0to10.Dayss BETWEEN 0 AND 10
JOIN trans AS t11to20 ON F.PartNum = t11to20.PartNum
AND t11to20.Dayss BETWEEN 11 AND 20
JOIN trans AS tover20 ON F.PartNum = tover20.PartNum
AND tover20.Dayss >20
GROUP BY F.PartNum,F.OnHandQty,F.IUM
Declared the OnHandQty and using cursor in a while loop will help to sort this out.
CREATE TABLE #OnHand(
PartNum NVARCHAR(100)
,OnHandQty DECIMAL
,IUM NVARCHAR(5)
)
INSERT INTO #OnHand
(PartNum, OnHandQty, IUM)
VALUES
('100009', 19430.00, 'KG')
CREATE TABLE #Trans(
TranDate DATETIME
,PartNum NVARCHAR(100)
,TranQty DECIMAL
,IUM NVARCHAR(5))
INSERT INTO #Trans
(TranDate, PartNum, TranQty, IUM)
VALUES
('2014-09-01', '100009', 10720.000, 'KG')
,('2014-09-01', '100009', 1340.000, 'KG')
,('2014-08-11', '100009', 8710.000, 'KG')
,('2014-08-11', '100009', 3350.000, 'KG')
,('2014-06-30', '100009', 9380.000, 'KG')
DECLARE #OnHand_Running DECIMAL
,#OnHandQty DECIMAL
,#TranQty DECIMAL
,#TranDate DATETIME
,#PartNum NVARCHAR(100)
,#First10Days INT = 0
,#Second10Days INT = 0
,#Third10Days INT = 0
SET #PartNum = '100009';
Set #OnHandQty = (Select OnHandQty
FROM #OnHand
WHERE PartNum = #PartNum)
Set #OnHand_Running = #OnHandQty
DECLARE tran_cursor CURSOR
FOR SELECT T.TranQty, T.TranDate
FROM #Trans T
ORDER BY T.TranDate DESC
OPEN tran_cursor
FETCH NEXT FROM tran_cursor
INTO #TranQty, #TranDate
WHILE (##FETCH_STATUS = 0) AND (#OnHandQty > 0)
BEGIN
IF (#OnHandQty - #TranQty) < 0
BEGIN
PRINT CAST(#OnHandQty AS NVARCHAR(100)) + '-' + CAST(#TranQty AS NVARCHAR(100)) + '=' + CAST(#OnHandQty - #TranQty AS NVARCHAR(100)) + ' --Enough'
END
ELSE
BEGIN
PRINT CAST(#OnHandQty AS NVARCHAR(100)) + '-' + CAST(#TranQty AS NVARCHAR(100)) + '=' + CAST(#OnHandQty - #TranQty AS NVARCHAR(100)) + ' --Not Enough'
END
IF (DATEDIFF(DAY, #TranDate, CURRENT_TIMESTAMP) < 10)
SET #First10Days = #First10Days + #TranQty
IF (DATEDIFF(DAY, #TranDate, CURRENT_TIMESTAMP) BETWEEN 10 AND 20)
SET #Second10Days = #Second10Days + #TranQty
IF (DATEDIFF(DAY, #TranDate, CURRENT_TIMESTAMP) > 20)
SET #Third10Days = #Third10Days + #TranQty
SET #OnHandQty = #OnHandQty - #TranQty
FETCH NEXT FROM tran_cursor
INTO #TranQty, #TranDate
END
SELECT #PartNum, #OnHand_Running, 'KG', #First10Days '[0-10] Days', #Second10Days '[11-20] Days', #Third10Days '[over 21 days]'
CLOSE tran_cursor;
DEALLOCATE tran_cursor;
RETURN

SQL Server: calculate field data from fields in same table but different set of data

I was looking around and found no solution to this. I´d be glad if someone could help me out here:
I have a table, e.g. that has among others, following columns:
Vehicle_No, Stop1_depTime, Segment_TravelTime, Stop_arrTime, Stop_Sequence
The data might look something like this:
Vehicle_No Stop1_DepTime Segment_TravelTime Stop_Sequence Stop_arrTime
201 13000 60 1
201 13000 45 2
201 13000 120 3
201 13000 4
202 13300 240 1
202 13300 60 2
...
and I need to calculate the arrival time at each stop from the departure time at the first stop and the travel times in between for each vehicle. What I need in this case would look like this:
Vehicle_No Stop1_DepTime Segment_TravelTime Stop_Sequence Stop_arrTime
201 13000 60 1
201 13000 45 2 13060
201 13000 120 3 13105
201 13000 4 13225
202 13300 240 1
202 13300 60 2 13540
...
I have tried to find a solution for some time but was not successful - Thanks for any help you can give me!
Here is the query that still does not work - I am sure I did something wrong with getting the table from the database into this but dont know where. Sorry if this is a really simple error, I have just begun working with MSSQL.
Also, I have implemented the solution provided below and it works. At this point I mainly want to understand what went wrong here to learn about it. If it takes too much time, please do not bother with my question for too long. Otherwise - thanks a lot :)
;WITH recCTE
AS
(
SELECT ZAEHL_2011.dbo.L32.Zaehl_Fahrt_Id, ZAEHL_2011.dbo.L32.PlanAbfahrtStart, ZAEHL_2011.dbo.L32.Fahrzeit, ZAEHL_2011.dbo.L32.Sequenz, ZAEHL_2011.dbo.L32.PlanAbfahrtStart AS Stop_arrTime
FROM ZAEHL_2011.dbo.L32
WHERE ZAEHL_2011.dbo.L32.Sequenz = 1
UNION ALL
SELECT t. ZAEHL_2011.dbo.L32.Zaehl_Fahrt_Id, t. ZAEHL_2011.dbo.L32.PlanAbfahrtStart, t. ZAEHL_2011.dbo.L32.Fahrzeit,t. ZAEHL_2011.dbo.L32.Sequenz, r.Stop_arrTime + r. ZAEHL_2011.dbo.L32.Fahrzeit AS Stop_arrTime
FROM recCTE AS r
JOIN ZAEHL_2011.dbo.L32 AS t
ON t. ZAEHL_2011.dbo.L32.Zaehl_Fahrt_Id = r. ZAEHL_2011.dbo.L32.Zaehl_Fahrt_Id
AND t. ZAEHL_2011.dbo.L32.Sequenz = r. ZAEHL_2011.dbo.L32.Sequenz + 1
)
SELECT ZAEHL_2011.dbo.L32.Zaehl_Fahrt_Id, ZAEHL_2011.dbo.L32.PlanAbfahrtStart, ZAEHL_2011.dbo.L32.Fahrzeit, ZAEHL_2011.dbo.L32.Sequenz, ZAEHL_2011.dbo.L32.PlanAbfahrtStart,
CASE WHEN Stop_arrTime = ZAEHL_2011.dbo.L32.PlanAbfahrtStart THEN NULL ELSE Stop_arrTime END AS Stop_arrTime
FROM recCTE
ORDER BY ZAEHL_2011.dbo.L32.Zaehl_Fahrt_Id, ZAEHL_2011.dbo.L32.Sequenz
A recursive CTE solution - assumes that each Vehicle_No appears in the table only once:
DECLARE #t TABLE
(Vehicle_No INT
,Stop1_DepTime INT
,Segment_TravelTime INT
,Stop_Sequence INT
,Stop_arrTime INT
)
INSERT #t (Vehicle_No,Stop1_DepTime,Segment_TravelTime,Stop_Sequence)
VALUES(201,13000,60,1),
(201,13000,45,2),
(201,13000,120,3),
(201,13000,NULL,4),
(202,13300,240,1),
(202,13300,60,2)
;WITH recCTE
AS
(
SELECT Vehicle_No, Stop1_DepTime, Segment_TravelTime,Stop_Sequence, Stop1_DepTime AS Stop_arrTime
FROM #t
WHERE Stop_Sequence = 1
UNION ALL
SELECT t.Vehicle_No, t.Stop1_DepTime, t.Segment_TravelTime,t.Stop_Sequence, r.Stop_arrTime + r.Segment_TravelTime AS Stop_arrTime
FROM recCTE AS r
JOIN #t AS t
ON t.Vehicle_No = r.Vehicle_No
AND t.Stop_Sequence = r.Stop_Sequence + 1
)
SELECT Vehicle_No, Stop1_DepTime, Segment_TravelTime,Stop_Sequence, Stop1_DepTime,
CASE WHEN Stop_arrTime = Stop1_DepTime THEN NULL ELSE Stop_arrTime END AS Stop_arrTime
FROM recCTE
ORDER BY Vehicle_No, Stop_Sequence
EDIT
Corrected version of OP's query - note that it's not necessary to fully qualify the column names:
;WITH recCTE
AS
(
SELECT Zaehl_Fahrt_Id, PlanAbfahrtStart, Fahrzeit, L32.Sequenz, PlanAbfahrtStart AS Stop_arrTime
FROM ZAEHL_2011.dbo.L32
WHERE Sequenz = 1
UNION ALL
SELECT t.Zaehl_Fahrt_Id, t.PlanAbfahrtStart, t.Fahrzeit,t.Sequenz, r.Stop_arrTime + r.Fahrzeit AS Stop_arrTime
FROM recCTE AS r
JOIN ZAEHL_2011.dbo.L32 AS t
ON t.Zaehl_Fahrt_Id = r.Zaehl_Fahrt_Id
AND t.Sequenz = r.Sequenz + 1
)
SELECT Zaehl_Fahrt_Id, PlanAbfahrtStart, Fahrzeit, Sequenz, PlanAbfahrtStart,
CASE WHEN Stop_arrTime = PlanAbfahrtStart THEN NULL ELSE Stop_arrTime END AS Stop_arrTime
FROM recCTE
ORDER BY Zaehl_Fahrt_Id, Sequenz
I'm quite sure this works:
SELECT a.Vehicle_No, a.Stop1_DepTime,
a.Segment_TravelTime, a.Stop_Sequence, a.Stop1_DepTime +
(SELECT SUM(b.Segment_TravelTime) FROM your_table b
WHERE b.Vehicle_No = a.Vehicle_No AND b.Stop_Sequence < a.Stop_Sequence)
FROM your_table a
ORDER BY a.Vehicle_No