I have the following data:
[Receipt] [Date] [Barcode] [Quantity] [Supplier] [DeliveryID]
0001 01/01/2000 0000001 5 Grocery NULL
0001 01/01/2000 0000002 7 Grocery NULL
0001 01/01/2000 0000571 2 Grocery NULL
0002 01/01/2000 0000041 5 Grocey NULL
0002 01/01/2000 0000701 10 Grocey NULL
0003 01/01/2000 0000001 9 Groceri NULL
What can I do to put an incrementing value to the DeliveryID?
As you can see, there is nothing unique that can be used to distinguish a row from another row. There is a large chance that a similar data like any of those rows may be entered again.
Unfortunately, I cannot delete the table and create a new one for the sake of the new column.
I tried counting all the null rows first,
SELECT COUNT(*) as TotalCount FROM dbo.Delivery WHERE DeliveryID IS NULL
And create a for loop to update.
But I realized that after the first loop, all null will be replaced by 1, instead of updating each row per loop.
I have thought of combining the Receipt and Supplier to become a unique value, but as I said earlier, there's a chance that a similar data may be entered, thus creating a duplicate row, losing the uniqueness of the row
Use a row_number
with D as
(
select Receipt, Date, Barcode, DeliveryID, row_number() over(order by receipt , Date, Barcode) as rn
from delivery
)
update D
set DeliveryID = rn
where DeliveryID is null
You can even partition by receipt to provide a per-line within the receipt group:
with D as
(
select Receipt, Date, Barcode, DeliveryID, row_number() over(partition by receipt order by Date, Barcode) as rn
from delivery
)
update D
set DeliveryID = rn
where DeliveryID is null
You could use these columns:
[Receipt] [Date] [Barcode] [Quantity]
as a PrimaryKey so you can identify the rows you need.
Or for the column [Delivery ID] you could use the IDENTITY function:
https://blog.sqlauthority.com/2013/07/27/sql-server-how-to-an-add-identity-column-to-table-in-sql-server/
http://www.dailyfreecode.com/code/identity-function-439.aspx
Add column with identity that would help you
like
alter table tableName add DeliveryID int Identity(1,1)
Related
i have this table
series
id
1975
1
1985
1
1995
2
2000
2
what we trying to achieve is we add alphabet increment where id is same, example series will be 1975A, 1985B, and then 1995A 2000B when id is same, it is possible to do that? in query or in c# mvc code?
You can use below query.
At first,
I have added row number par group/ partition
Then as we know CHR(65)='A', Thus I have added 64 + auto row_rumber
And Convert to CHAR.
Add result with series field.
SELECT
CONCAT
(
series ,
CHR(64 + CAST ( row_number() OVER(PARTITION BY id order by id) AS integer ))
)
,id from table1
I have a temporary table with one column containing 3 pieces of data: Code, Date, and Quantity.
Example:
-------
FR123456
24/02/1988
500
I need to extract the data in this column into separate columns.
Example:
Code | Date | Quantity
--------- ----------- ----
FR123456 | 24/02/1988 | 500
I used this code:
SELECT [1], [2], [3]
FROM
(
SELECT row_number() OVER (ORDER BY splitdata DESC) AS Id, splitdata
FROM splitdata
) AS SourceTable
PIVOT
(
MIN (splitdata)
FOR id IN ([1], [2], [3])
) AS PivotTable;
The problem with it is that once the content of data changes, I may get the quantity content into the date column due to the aggregate function (MIN).
I assume this is SQL-Server related...
Your problem is: A SQL-Server table does not have any kind of implicit sort order. A simple SELECT * FROM SomeWhere can return in the sort order you've inserted your data, but can return completely different as well. The only chance to ensure a sort order is an ORDER BY at the outer-most query against a (set of) unique column(s).
You can create a sort order by kind of analysing your data:
This is a mockup-table with your test data:
DECLARE #mockup TABLE(YourColumn VARCHAR(100));
INSERT INTO #mockup VALUES
('FR123456')
,('24/02/1988')
,('500');
--The query will check the values if they can be casted to a number, to a date or not.
--This will be used to place a sort order to the values.
--I use 105 in CONVERT to enforce the dateformat dd-MM-yyyy
SELECT CASE WHEN TRY_CONVERT(DATE,YourColumn,105) IS NOT NULL THEN 2
ELSE CASE WHEN TRY_CAST(YourColumn AS INT) IS NOT NULL THEN 3 ELSE 1
END
END AS SortOrder
,YourColumn
FROM #mockup
ORDER BY SortOrder;
But if there are several triplets in your table, not just one as in your sample, I'm afraid you're lost...
Btw: Your own approach tries to do exactly the same:
SELECT row_number() OVER (order by splitdata desc)as Id
This will create kind of a sort order number, but it will be random (a quantity will appeare before or after the date depending on alphanumerical rules).
Hint
Add an IDENTITY column to your table. This will use an increasing number for any row the moment it is created. These values can be used to enforce the order as inserted (by using ORDER BY with this column).
UPDATE: Your query
SELECT [1], [2] , [3]
FROM
(SELECT CASE WHEN TRY_CONVERT(DATE,splitdata,105) IS NOT NULL THEN 2
ELSE CASE WHEN TRY_CAST(splitdata AS INT) IS NOT NULL THEN 3 ELSE 1
END
END AS Id , splitdata
from #mockup ) AS SourceTable
PIVOT
(
MIN (splitdata)
FOR id IN ([1], [2], [3])
) AS PivotTable;
Okay so I am accepting payments on my site (via Authorize.Net). The payment form redirects to a receipt page.
I will have a column in the database for an invoice code (column InvoiceCode), which is RRC0A in this instance. Then I will have another column for an 8 digit number (column InvoiceNumber). Then I will have InvoiceCode + InvoiceNumber = InvoiceId. For example, the InvoiceId will be RRC0A + 8 numbers. It will increment as such: 00000000, 00000001, 00000002, etc. Therefore the InvoiceId will be RRC0A00000001. I cannot simply increment the column in my database because there will be other InvoiceCodes that also start at 00000000.
I need to increment the InvoiceNumber by one when I add a new row. How can I grab the last InvoiceNumber that was entered into the database? It must be associated with the InvoiceCode RRC0A. This could occur when more than 1 person is making a payment, so I am not sure of the best way.
How can I pad the incrementing InvoiceNumber with 0's in front so that it is always 8 digits?
Using an identity and a computed column you can created you invoice numbers with the correct formatting at the time of insert.
CREATE TABLE [dbo].[Invoices](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Code] [nchar](5) NOT NULL,
[InvoiceNumber] AS ([Code]+right('00000000'+CONVERT([nvarchar](10),[ID]),(8))) PERSISTED,
[Cost] [decimal](18, 2) NOT NULL,
CONSTRAINT [PK_Invoices] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
)
sample bulk insert
INSERT INTO [dbo].[Invoices] ([Code], [Cost])
OUTPUT INSERTED.*
SELECT 'ABC01', 500 UNION ALL
SELECT 'ABC01', 501 UNION ALL
SELECT 'EFG23', 502 UNION ALL
SELECT 'RRAc1', 503 UNION ALL
SELECT 'ABC01', 504
output
ID Code InvoiceNumber Cost
1 ABC01 ABC0100000001 500.00
2 ABC01 ABC0100000002 501.00
3 EFG23 EFG2300000003 502.00
4 RRAc1 RRAc100000004 503.00
5 ABC01 ABC0100000005 504.00
When you insert your records you can get the ID and InvoiceNumber back at the same time.
The values are also persisted so they may be indexed as you would other columns.
SELECT InvoiceCode, MAX(InvoiceID)
FROM yourTable t
GROUP BY InvoiceCode
This should return the latest InvoiceID for each InvoiceCode, but you can add your own WHERE clause to filter it down
As for how to pad-left in sql, check out this answer.
A as in one column is just a bad design
Have composite PK
InvCode (varchar), InvInt (int)
declare #InvCode varchar(20) = 'RRC0A'
insert into invoice (InvCode, InvInt)
OUTPUT INSERTED.InvInt, INSERTED.InvCode
select #InvCode, isnull(max(InvInt),-1) + 1
from invoice
where InvCode = #InvCode;
The isnull will deal with the first one
A single statement is a transaction so I don't think two simultaneous could clobber
Even if they did the PK would be violated so the insert would fail
use a view or a computed column for the formatted invoice number
CREATE TABLE [dbo].[Invoice](
[InvCode] [varchar](10) NOT NULL,
[InvInt] [int] NOT NULL,
[Formatted] AS ([InvCode]+right('00000000'+CONVERT([nvarchar](10),[InvInt]),(8))),
CONSTRAINT [PK_Invoice] PRIMARY KEY CLUSTERED
(
[InvCode] ASC,
[InvInt] ASC
)
You can grab the last InvoiceNumber with a SELECT query.
You can pad the invoice number with the + sign to concatenate two strings, and then use RIGHT() to get the right-most 8 characters.
Finding a solution to an issue in my project
I have stages associated with contracts. That is, a contract can be in either Active stage, Process stage or Terminated stage.
I need to get the no the days the contract was in each stage.
For example, if a contract C1 was in Active stage from 20/10/2013 to 22/10/2013, then in the Process stage from 22/10/2013 to 25/10/2013 and finally in Terminated stage from 25/10/2013 to 26/10/2013 and then again in Active from 26/10/2013 to 28/10/2013, then I should get as result
Active = 4days
Process = 3days
Terminated = 1day /likewise something
My table is created with these columns:
EntryId (primary key)
StageId (foreign key to Stage table)
ContractId (foreign key to contract table)
DateofStageChange
How to do this in SQL Server?
As asked pls find the table entries:
EntryID | Stage ID | Contract ID | DateChange
1 | A1 | C1 |20/10/2013
2 | P1 | C1 |22/10/2013
3 | T1 | C1 |25/10/2013
4 | A1 | C1 |26/10/2013
5 | P1 | C1 |28/10/2013
6 | T1 | C1 |Null(currently in this stage)
Need to use group by on Stage ID
it is important to check and make sure how data is populated in your table.Based on just your sample data and also note that if your entryid is not in sequence then you can create one sequence using row_number.
declare #t table(EntryId int identity(1,1), StageId int,ContractId varchar(10),DateofStageChange date)
insert into #t values
(1,'C1','2013-10-20'),(1,'C1','2013-10-22'),(2,'C1','2013-10-22'),(2,'C1','2013-10-25')
,(3,'C1','2013-10-25'),(3,'C1','2013-10-26'),(1,'C1','2013-10-26'),(1,'C1','2013-10-28')
Select StageId,sum([noOfDays]) [totalNofDays] from
(select a.StageId,a.ContractId,a.DateofStageChange [Fromdate],b.DateofStageChange [ToDate]
,datediff(day,a.DateofStageChange,b.DateofStageChange) [noOfDays]
from #t a
inner join #t b on a.StageId=b.StageId and b.EntryId-a.EntryId=1)t4
group by StageId
You can't with your current structure.
You can get the latest one by doing datediff(d, getdate(), DateOfStageChange)
but you don't have any history so you can't get previous status
This can be done in SQL with CTE.
You didnt provide your tablenames, so you'll need to change where I've indicated below, but it would look like this:
;WITH cte
AS (
SELECT
DateofStageChange, StageID, ContractID,
ROW_NUMBER() OVER (ORDER BY ContractID, StageId, DateofStageChange) AS RowNum
FROM
DateOfStageChangeTable //<==== Change this table name
)
SELECT
a.ContractId,
a.StageId,
Coalesce(sum(DATEDIFF(d ,b.DateofStageChange,a.DateofStageChange)), 'CurrentState`) as Days
FROM
cte AS A
LEFT OUTER JOIN
cte AS B
ON A.RowNum = B.RowNum + 1 and a.StageId = b.StageId and a.ContractId = b.ContractId
group by a.StageId, a.ContractId
This really is just a self join that creates a row number on a table, orders the table by StageID and date and then joins to itself. The first date on the first row of the stage id and date, joins to the second date on the second row, then the daterange is calculated in days.
This assumes that you only have 2 dates for each stage, if you have several, you would just need to do a min and max on the cte table.
EDIT:
Based on your sample data, the above query should work well. Let me know if you get any syntax errors and I'll fix them.
I added a coalesce to indicate the state they are currently in.
I am working on a website that does random selections of employees for random drug test. I am trying to figure out a report/ code using SQL Server 2008, ASP.NET, and C#.
Here is an example of what I have worked on so far:
I need to do is generate a report of all employees for a specific company where the employees are assign a number. Example of this code is as follows:
SELECT
dbo.names2.ssn, dbo.names2.firstname, dbo.names2.lastname,
ROW_NUMBER() over(order by dbo.names2.ssn) as RowNumber
FROM
dbo.names2
WHERE
dbo.names2.code = 8562
This query return 12 records number 1-12 with the Employees social security number, first name, and last name.
I now need to figure out a query so that when I go to my asp.net webpage and enter that I need 5 employees to be randomly tested that I get a query that returns the row number the employee is associated with in the query above on one page of the report, and on the second page of the report return the number assigned in the query above along with the employees SSN, First, and last name.
Thanks,
ty
I would ORDER BY NEWID() which generates a random GUID and SELECT TOP 5.
Edited. This query has 2 return results. 1 is the full list of employees and the other is just the list of 5 randomly selected numbers that corresponds to the rownum on the employee list.
IF (OBJECT_ID(N'tempdb..#tempTable') IS NOT NULL)
DROP TABLE #tempTable ;
CREATE TABLE #tempTable
(
RowNum INT ,
SSN VARCHAR(16) ,
FirstName VARCHAR(64) ,
LastName VARCHAR(64)
);
INSERT INTO [#tempTable]
([RowNum] ,
[SSN] ,
[FirstName] ,
[LastName]
)
SELECT ROW_NUMBER() OVER(ORDER BY dbo.names2.ssn) AS RowNum ,
dbo.names2.ssn ,
dbo.names2.firstname ,
dbo.names2.lastname
FROM dbo.names2
WHERE dbo.names2.code = 8562
SELECT [RowNum] ,
[SSN] ,
[FirstName] ,
[LastName]
FROM [#tempTable] AS tt
SELECT TOP 5 RowNum
FROM [#tempTable] AS tt
ORDER BY NEWID()