Delete entries of a specific time range - sql-server

I want to delete from an existing table the entries that respond to a specific time range if they exist in this table, then calculate them and insert them to it.
If they do not exist create them and just insert to the table.
How is that possible to be done?
Could anyone give an example of this?
The table structure should be the following:
create table test_table
(
[Date] float
,[UserName] nvarchar(max)
,[SessionType] int
,[Duration] float
,[MessageCount] int
)

if you have a Column that Stores the DATE and TIME then you can just delete the records based on that.
Suppose I have a Column Called CreateDate on My table. Then I can Delete all records Created between 10.00 am and 11.00 Today by Just Giving
DELETE FROM MyTable WHERE
CreateDate BETWEEN '2018-01-12 10:00:00.000' AND '2018-01-12 11:00:00.000'
Now Insert the values again using the Normal INSERT statement

You can do in steps like this
First store the set of records in time range in a temp table
SELECT * INTO tempTable FROM YourTable WHERE CONVERT(FLOAT, [Date]) BETWEEN 43100.3603763503 AND 43110.3603763503
Then delete the records from the table
DELETE FROM YourTable WHERE CONVERT(FLOAT, [Date]) BETWEEN 43100.3603763503 AND 43110.3603763503
Then do the calculations as per your requirement with the data available in tempTable and insert the data into your table
INSERT INTO YourTable
SELECT * FROM tempTable
Then drop the tempTable
DROP TABLE tempTable

I am updating my solution to this thank you all for help.
create mytable table
(
[Date] float
,[UserName] nvarchar(max)
,[SessionType] int
,[Duration] float
,[MessageCount] int
)
IF EXISTS (SELECT * FROM mytable WHERE [Date] >= 43082 AND [Date] < 43111)
BEGIN
DELETE FROM mytable WHERE [Date] >= 43082 AND [Date]< 43111
;WITH Data AS (
/*do the calculation of data*/
)
INSERT INTO mytable select * from Data
END
ELSE
BEGIN
;WITH Data AS (
/*do the calculation of data*/
)
INSERT INTO mytable select * from Data
END

Related

SQL Server set based processing for orders and details

I have been trying to get acclimated to set based processing with SQL Server. Below is a simplified version of cursor processing for this task. It involves creating an order from items in a shopping cart. The order is created, line items are added to the order details table, the total is accumulated and eventually updated on the order table. Can anyone suggest how to do this with a set based approach instead of a cursor?
One other question is that in most cases the cursor will process at most 10 or 12 line items at a time. Is that enough of a reason to not have to consider the set based approach?
declare getCart2 cursor for
select MemberID,ProductID,Quantity,Price
from Carts
where MemberID = #MemberID
open getCart2
fetch next from getCart2 into #MemberID,#ProductID,#Quantity,#Price
Insert into Orders
(MemberID,TotalAmount0
Values
(#MemberID, 0.00)
set #OrderID = ##Identity
while ##FETCH_STATUS = 0 Begin
Insert into OrderDetails
(OrderID,ProductID,Quantity)
Values
(#OderID,#ProductID,#Quantity)
set #TotalAmout = #TotalAmount + (#Quantity * #Price)
set #PrevMemberID = #MemberID
fetch next from getCart2 into #MemberID,#ProductID,#Quantity,#Price
End
close getCart2
deallocate getCart2
Update Orders
Set TotalAmount = #TotalAmount
Where OrderID = #OrderID
Thanks for your help.
Here goes an approach:
In this case I am creating a temporary table variable that will store the order id's on it.
Then, it performs the insertions on the Order table and after that, in the OrderDetails.
Finally, it computes the TotalAmount and updates on the Orders table.
Although you don't have it in your code (and in mine as well), but I recommend you to use this code inside a transaction.
Hope it helps you improve your performance.
USE [tempdb];
GO
SET NOCOUNT ON;
IF OBJECT_ID(N'dbo.Carts', N'U') IS NOT NULL DROP TABLE [dbo].[Carts];
IF OBJECT_ID(N'dbo.Orders', N'U') IS NOT NULL DROP TABLE [dbo].[Orders];
IF OBJECT_ID(N'dbo.OrderDetails', N'U') IS NOT NULL DROP TABLE [dbo].[OrderDetails];
GO
-- Creates the tables like you have
CREATE TABLE [dbo].[Carts] (MemberID INT, ProductID INT, Quantity INT, Price DECIMAL(10, 2));
CREATE TABLE [dbo].[Orders] (OrderID INT IDENTITY(1, 1), MemberID INT, TotalAmount DECIMAL(10, 2));
CREATE TABLE [dbo].[OrderDetails] (OrderID INT, ProductID INT, Quantity INT);
-- Inserts dummy data
INSERT INTO [dbo].[Carts] VALUES (1001, 80, 5, 25.00);
INSERT INTO [dbo].[Carts] VALUES (1002, 120, 2, 12.90);
INSERT INTO [dbo].[Carts] VALUES (1010, 70, 3, 12.00)
INSERT INTO [dbo].[Carts] VALUES (1034, 176, 5, 45.00);
-- Temporary table that stores the inserted Order ID's
DECLARE #OrdersToProcess TABLE (OrderID INT, MemberID INT);
-- Inserts all Orders
INSERT INTO Orders (MemberID, TotalAmount)
OUTPUT inserted.OrderID, inserted.MemberID INTO #OrdersToProcess
SELECT MemberID, 0
FROM [dbo].[Carts]
-- Inserts order details
INSERT INTO OrderDetails (OrderID, ProductID, Quantity)
SELECT OrderID, ProductID, Quantity
FROM [dbo].[Carts] C
INNER JOIN #OrdersToProcess O ON C.MemberID = O.MemberID;
-- Updates order totals
UPDATE [dbo].[Orders]
SET TotalAmount = T.Total FROM
(
SELECT OrderID, SUM(Quantity * Price) AS [Total]
FROM [dbo].[Carts] C
INNER JOIN #OrdersToProcess O ON C.MemberID = O.MemberID
GROUP BY OrderID
) T
WHERE [dbo].[Orders].OrderID = T.OrderID
SELECT * FROM [dbo].[Orders];
SELECT * FROM [dbo].[OrderDetails];
Results:
As I understand your problem, this store procedure should be called when a particular member presses the check-out button, so it should create a single order with all the items in the cart of that member.
You can use something like this:
INSERT INTO Orders (MemberID, TotalAmount)
VALUES (#MemberID, 0)
SET #OrderID=SCOPE_IDENTITY()
INSERT INTO OrderDetails (OrderID, ProductID, Quantity)
SELECT OrderID, ProductID, Quantity
FROM [dbo].[Carts] C
WHERE C.MemberID=#MemberID
UPDATE dbo.Orders SET TotalAmount=(
SELECT SUM(c.Quantity*c.Price)
FROM dbo.Carts c
WHERE c.MemberID=#MemberID
) WHERE OrderID=#OrderID
It's true that this reads the Carts table twice, but with a proper index (on the MemberID column) that should be fast enough.

How To Set Limit Table Row SQL?

How to set limit table row in SQL Server?
I want to set limit of my table rows to 100 rows only.
So when the table have more than 100 rows, I want to delete first row then add new row to last row (100).
How can I do this?
One thing that i can assure you..
Create a trigger that if > 100 then delete first record record.
see here as your guide.
I think you hv to do two things
i) Create Trigger
declare #MaxRowLimit int=5
declare #t table(col1 int)
insert into #t values(1),(2),(3),(4),(5)
insert into #t VALUES(12)
;With CTE as
(
select top (#MaxRowLimit) col1
from #t t1
order by t1.col1 desc
)
,CTE1 as(
select * from #t t
where not exists
(select col1
from cte t1 where t.col1=t1.col1
)
)
delete from cte1
select * from #t
ii) If it is bulk insert then,you hv to do manipulation before bulk insert.
like if bulk insert count is greater than 100 then sort and keep last 100 rows and remove rest rows.

How to make a Trigger on Master-Detail

I Have the following scenario:
CREATE TABLE dbo.Orders
(
OrderID int IDENTITY (1,1) NOT NULL
, OrderVersion int DEFAULT(1)
, Customer varchar(30)
, ScheduleDate date
, PaymentOption int
);
CREATE TABLE dbo.OrdersItems
(
OrderItemsID int IDENTITY (1,1) NOT NULL
, OrderID int
, Product varchar(100)
, Qty int
, value decimal(18,2)
);
CREATE TABLE dbo.logOrders
(
OrderID int NOT NULL
, OrderVersion int DEFAULT(1)
, Customer varchar(30)
, ScheduleDate date
, PaymentOption int
);
CREATE TABLE dbo.logOrdersItems
(
OrderItemsID int NOT NULL
, OrderID int
, Product varchar(100)
, Qty int
, value decimal(18,2)
);
-- Insert values into the table.
INSERT INTO dbo.Orders (Customer , ScheduleDate, PaymentOption)
VALUES ('John', 2016-09-01, 1);
INSERT INTO dbo.OrdersItems( OrderId, Product, Qty, Value)
VALUES (1, 'Foo', 20, 35.658),
(1, 'Bla', 50, 100)
(1, 'XYZ', 10, 3589)
First Statement
UPDATE Orders set ScheduleDate = 2016-10-05 WHERE OrderId = 1
Second Statement
Delete From OrdersItems WHERE OrderItemsID = 2
UPDATE OrdersItems set Qty = 5 WHERE OrderItemsID = 1
Third Statement
Update Orders set PaymentOption = 2 WHERE OrderId = 1
Update OrdersItems set Value = 1050 WHERE OrderItemsID = 3
I am trying to figure out how to make a trigger that after each one of the Statements Sample above Insert on the log Tables the data before the changing. And setting the OrderVersion to OrderVersion + 1 on table Orders.
So on the log Tables I will have all versions after the later one.
Is it possible to make a single trigger to monitor both tables and execute getting the original data before the UPDATE, DELETE , INSERT statement to get the original data and INSERT on the logTables ?
Here comes a sample to explain better what result I want.
This is the Initial Data on table Orders and OrdersItems
If I make an Update on Orders ( any column ) or Make an Update,Insert,Delete on OrdersItems I need to Insert on respectively logTables the data on the image.
And with this I'll have on logOrders and logItems the original data and on the Orders and Items the altered data.
I Hope I could explain better what I mean.
You will need two triggers. The trigger for the Orders table handles Orders table update/delete. The trigger for the OrdersItems table does the same for OrdersItems. The triggers look like this:
For the Orders table:
CREATE TRIGGER dbo.Orders_trigger
ON dbo.Orders
AFTER DELETE,UPDATE
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.logOrders
SELECT * FROM DELETED;
INSERT INTO dbo.logOrdersItems
SELECT oi.* FROM OrdersItems oi
WHERE oi.OrderID IN (SELECT OrderId FROM DELETED);
END
GO
For OrdersItems:
CREATE TRIGGER dbo.OrdersItems_trigger
ON dbo.OrdersItems
AFTER DELETE,UPDATE
AS
BEGIN
SET NOCOUNT ON;
--Inerst the changed/deleted OrdersItems into the log
INSERT INTO dbo.logOrdersItems
SELECT * FROM DELETED
--Inserts the unchanged sibling OrdersItems records into the log
INSERT INTO dbo.logOrdersItems
SELECT oi.* FROM OrdersItems oi
WHERE oi.OrderId IN (SELECT DISTINCT OrderId FROM DELETED)
AND oi.OrderItemsID NOT IN (SELECT DISTINCT OrderItemsID FROM DELETED);
INSERT INTO dbo.logOrders
SELECT o.* FROM Orders o
WHERE o.OrderID IN (SELECT DISTINCT OrderId FROM DELETED);
END
GO
The Orders Trigger is fairly straightforward. Use the virtual DELETED table to insert the original version of the records into the log. Then join to the child OrdersItems records and insert them into the log as well. The way this is written, it will work even if you update or delete multiple Order records at a time.
The OrdersItems Trigger is a bit more complicated. You need to log the pre-chage version of the OrdersItems and Orders Records. But you also want (I think) to log the unchanged "sibling" OrdersItems records as well so that you have a complete picture of the records.
I know this is just your sample data, but you will want to add some kind of a timestamp to the records in the log tables. Otherwise you just end up with a bunch of duplicate rows and you cannot tell which is which. At the beginning of the trigger you can create a variable to hold the update datetime and then append that to your INSERT statement for the logs.
DECLARE #UpdateDateTime DATETIME;
SET #UpdateDateTime = GETUTCDATE();

How to pick random things which are conseq in table

create table TAB
(
id int,
Name Char(1)
);
insert into TAB(ID,NAME) values(1,'A')
insert into TAB(ID,NAME) values(1,'B')
insert into TAB(ID,NAME) values(2,'C')
insert into TAB(ID,NAME) values(2,'A')
insert into TAB(ID,NAME) values(2,'B')
insert into TAB(ID,NAME) values(3,'C')
insert into TAB(ID,NAME) values(3,'B')
this is my table and values, without using id column in where condition i need to get c,b and 3 alone from the table
Without the use of TOP / MAX or a WHERE clause :-
SET ROWCOUNT 2; -- Limit the query to just 2 rows
IF OBJECT_ID('tempdb..#tmp','U') IS NOT NULL DROP TABLE #tmp; -- Ensure #tmp table doesn't already exist
SELECT ID,Name,RANK() OVER (ORDER BY id DESC) as Rnk INTO #tmp FROM TAB
SELECT ID,Name FROM #tmp

Need T-SQL Query for Groups and Islands

create table #sample (rowguid int identity ,id_frm int ,id_to int)
insert into #sample values( 1,5)
insert into #sample values( 7,13)
insert into #sample values( 17,20)
In the above table I have values starting Id and Ending Id. I need to prepare a table which has all the numbers falls between starting Id and Ending Id
i have tried it with looping but response is very slow in real world.
any body help me with query ???
This is what I have tried so far...
declare #sql varchar(8000) = '
select top '+cast((select max(id_to) from #sample) as varchar(100))+' identity(int,1,1) as guidid into tally from sysobjects,syscolumns '
exec (#sql)
alter table Tally add slab varchar(10)
create clustered index idx on Tally(guidid)
create clustered index idx on #sample(id_frm asc,id_to desc)
update Tally set slab = rowguid
from #sample join Tally on guidid between id_frm and id_to
delete from Tally where slab is null
select * from Tally
This query works fine with small numbers
But My real time table have 13 digit nos. It through Arithmetic overflow error
Assuming the range id_frm and id_to is relatively small integers, e.g. < 1M, one technique to approach this problem is to create a table with all values in the range and join to it:
WITH lotsOfNumbers AS
(
SELECT ROW_NUMBER() OVER (ORDER BY o1.object_id) AS id
FROM sys.objects o1 CROSS JOIN sys.objects o2
)
INSERT INTO #targetTable
SELECT l.ID
FROM lotsOfNumbers l
INNER JOIN #sample
ON l.ID BETWEEN #sample.id_frm AND #sample.id_to;
SqlFiddle here
A permanent table with the necessary range of ID's and a clustered index on the ID would improve performance, obviously.
Add in a DISTINCT if your ranges overlap, and you don't want duplicates in the result.
If you are able to get a full range of acceptable values into another table, you can use it without looping. The meathod below gets the minimum (1) and maximum (20), and the temporary table named #range will return everything in between.
drop table #sample
drop table #range
create table #sample (id_frm int ,id_to int)
insert into #sample values( 1,5)
insert into #sample values( 7,13)
insert into #sample values( 17,20)
create table #range (id int)
insert into #range select 1
go
insert into #range select top 1 max(id)+ 1 from #range
go 100
declare #min int
declare #max int
set #min= (select min(id_frm ) from #sample )
set #max = (select max(id_to) from #sample )
select * from #range where id between #min and #max

Resources