Hi' I'm working with an asp.net application wich related to the registration of students, the data related to the students is inserted in to a database, each time a student is registered the field idStudent is incremented by one, what I want to do is when a new year begins reset the student value in order to begin from 1 in the new year.
idStudent Year 1 2011 2 2011 3
2011 4 2011 5 2011 ..... 1 2012 2
2012 3 2012 .......
How can I do this?
The databse is in sql server 2008
Hope your help
If I had this exact business requirement and I couldn't negotiate a better, more efficient way then this would be my approach:
Instead of using an artificial key (i.e. an identity column) I would utilize a composite key. To find out what your best bet for a composite key would be, you need to know the business rules and logic. In other words, a question you would have to ask is is the combination of year and id unique? In other words, per year a student id can only be used once...?
This is one of those times were you would benefit from a natural composite key.
You could add a computed column which derives the number based on the year. You just need to run the script below at the start of the new year. Do note that when a transaction is rolled back there will be gaps in the identity column. (and inserts in a previous year will create big gaps as well.)
-- test table & inserts
create table Students (Id int identity, year int, name varchar(20), StudentId int null)
insert into Students (year, name) values (2010, 'student1'), (2011, 'student1'), (2011, 'student2')
-- run this every year
EXEC ('ALTER TABLE Students DROP COLUMN StudentId ')
declare #count int, #sql varchar(max), #year int
declare c cursor local read_only
for select year + 1, max(Id) from Students group by year
open c
fetch next from c into #year, #count
select #sql = 'when year = ' + convert(varchar(10), #year - 1) + ' then Id '+ CHAR(13) + CHAR(10)
while ##FETCH_STATUS = 0
begin
select #sql = #sql + 'when year = ' + convert(varchar(10), #year) + ' then Id - ' + convert(varchar(10), #count) + CHAR(13) + CHAR(10)
fetch next from c into #year, #count
end
close c
deallocate c
select #sql = 'CASE ' + CHAR(13) + CHAR(10) + #sql + ' ELSE 0 END'
select #sql = 'ALTER TABLE Students ADD StudentId AS ' + isnull(#sql, 'Id') + ' PERSISTED'
exec (#sql)
Related
I have This below query its working fine for Month Text in English but we need Month Text in Arabic How we do??I have Sql Server 2008R2.I have check using FORMAT function but its not work in 2008r2 edition.
DECLARE #tempdate TABLE
(
pricedate DATETIME NOT NULL,
priceid INT NOT NULL
)
INSERT INTO #tempdate
(pricedate,
priceid)
SELECT pricelist_date,
pricelist_id
FROM vw_lu_region_and_date_list
WHERE price_status = '3'
AND region_id = '1'
AND saletype = '2'
ORDER BY pricelist_date DESC;
WITH numbered
AS (SELECT *,
Row_number()
OVER (
partition BY Dateadd(month, Datediff(month, 0, pricedate), 0
)
ORDER BY pricedate DESC) AS rn
FROM #tempdate)
SELECT RIGHT(CONVERT(NVARCHAR(20), pricedate, 106), 8) AS PRICELIST_DATE,
priceid AS PRICELIST_ID
FROM numbered
WHERE rn = 1
ORDER BY priceid DESC
I have get result from above query like
Apr 2013
Mar 2013
but we need like Apr and Mar in Arabic????
I also suggest to store as normal date and you can probably convert in your client application rather than in SQL.
In the organization I once worked for the previous developer designed a SQL CLR function to convert dates into Hebrew dates and return in Hebrew.
But You Can Use This :
CREATE FUNCTION dbo.fnTranslateMonthNameToArabic
(#date as datetime)
RETURNS nvarchar(50)
AS
BEGIN
DECLARE #result AS nvarchar(50);
IF MONTH(#date) = 1
SET #result = (SELECT CONVERT(nvarchar(2), DAY(#date)) + N' ' + N'يناير' + N' ' + CONVERT(nvarchar(4), YEAR(#date)));
IF MONTH(#date) = 2
SET #result = N'and so on ...';
RETURN #result;
END
Go
-- Test
SELECT dbo.fnTranslateMonthNameToArabic({d N'2012-01-16'}) AS Arabic
At Last Please Take a Look at Arabic Language Support in SQL Server
I am retrieving two or more tables data based on conditions, so I am writing cursors in SQL server2005 like this:
create PROC [dbo].[uspCustomerInvoiceGetlist]
#CustomerID varchar(20)
AS
BEGIN
SELECT DeleteStatus,InvoiceID,CONVERT(varchar(16),CreationDate,101) + ' ' +
CONVERT(varchar(16),CreationDate,8) as CreationDate,AccountNumber,Sum(Amount) as Amount from tblInvoiceDetails where CustomerID=#CustomerID Group By InvoiceID,CreationDate,AccountNumber,DeleteStatus
END
alter procedure uspCustomerInvoiceGetlist1(#CustomerID varchar(50)) as
Begin
Declare #InvoiceID int, #Balance float
Declare MyCur Cursor for select InvoiceID from tblInvoiceHeader where CustomerID=#CustomerID
Open MyCur
Fetch next from mycur into #InvoiceID
While ##Fetch_Status=0
Begin
set #Balance=(select sum(Balance) from tblInvoicePaymentDetails where CustomerId=#CustomerID and InvoiceId=#InvoiceID)
print #Balance
if #Balance!=0
SELECT h.DeleteStatus,h.InvoiceID,CONVERT(varchar(16),h.CreationDate,101) + ' ' +
CONVERT(varchar(16),h.CreationDate,8) as CreationDate,h.AccountNumber,Sum(h.Amount) as Amount, #Balance as Balance from tblInvoiceDetails h inner join tblInvoicePaymentDetails p on h.CustomerID=p.CustomerID and h.InvoiceID=#InvoiceID
Group By h.InvoiceID,h.CreationDate,h.AccountNumber,h.DeleteStatus
else
SELECT DeleteStatus,InvoiceID,CONVERT(varchar(16),CreationDate,101) + ' ' +
CONVERT(varchar(16),CreationDate,8) as CreationDate,AccountNumber,Sum(Amount) as Amount, 0 as Balance from tblInvoiceDetails where CustomerID=#CustomerID and InvoiceID=#InvoiceID Group By InvoiceID,CreationDate,AccountNumber,DeleteStatus
Fetch Next From MyCUr into #InvoiceID
End
Close Mycur
Deallocate Mycur
End
output is correct like that (two outputs based on condition two are more)
Status InvoiceID Date account no Amount Balance
1 1009 06/21/2011 10:22:15 10009 450 350
Status InvoiceID Date account no Amount Balance
1 1010 06/21/2011 10:22:33 100000 690 0
But I can bind the all values (both) in grid view in ASP.NET 2.0. How is it possible?
In the Front End, You will get Two DataTable.
You just Combine those two DataTable into a Single One.
And Bind the DataTable with the GridView.
Merge like this:
dt1.Merge(dt2); //dt1 is the DataTable 1 and dt2 is the DataTable 2
Get the Set of Tables as DataSet and Merge using For Loop: I have given code below:
DataTable dtmerge = new DataTable();
for (int i = 0; i < ds.Tables.Count; i++) // ds is the DataSet
{
dtmerge.Merge(ds.Tables[i]);
}
I have a database which contains 2 fields called DateOfBirth and Age, for storing users DOB and age respectively. I want the Age column to be automatically incremented by 1 every year, according to the DOB matching server date.
What could be the best way for achieving this? I am using asp.net and sql server 2008.
Rather than store both the DateOfBirth and Age, create a computed column on the table that calculates the age:
[Age] AS datediff(year, DateOfBirth, getdate())
So in yout table creation:
-- Create Table with computed column
CREATE TABLE [dbo].[CCtest]
(
[id] [int] not NULL,
[DateOfBirth] [datetime] NULL,
-- etc...
[Age] AS datediff(year, DateOfBirth, getdate())
)
GO
If you want to persist the computed value add the PERSISTED keyword.
One possibility, if you want Age displayed in years and months:
[AgeInDays] AS datediff(day, DateOfBirth, getdate())
then create a view over your table that formats AgeInDays into years and months.
Here is another possibility, using a computed column of [AgeYears]:
create view vwCCtestAge
AS
select
id,
dateofbirth,
cast([AgeYears] as varchar(4)) + ' years ' +
cast(datediff(month, DateOfBirth, getdate())
- case when (AgeYears > 0) then (AgeYears - 1)*12
else 0
end as varchar(4)) + ' months' as Age
from cctest2
GO
[You should check for boundary cases...]
I have created one stored procedure which runs on 5000 users in tbluser table with some filter condition in database.There are 4 filtering condition(FC1,FC2,FC3,FC4).Filtering condition has some ListBox and dropdown list of department and countries.I want output as given below:
ID Name StaffNo department Points
1 KK 111 dep1 2
2 NN 222 dep2 1
3 DD 333 dep3 4
I got ID,Name,StaffNo,department in resultset but not points.
points calculation would be based on filtering condition like
if FC1 matched user gained point 1,if both FC1 and FC2 matched user gained 2 point,if both FC1 ,FC2 and FC3 matched user gained 3 point etc.
--in stored procedure i m using dynamic query
DECLARE #SQL VARCHAR(2000)
SET #SQL = 'SELECT U.UserID, U.StaffNo,U.FirstName+'' ''+ U.LastName AS EmployeeName,''?'' AS Points FROM tblUser U '
SET #SQL = #SQL+' WHERE U.Department in (' + #SqlDepartment + ') '
---------------------Update---------------------------------------
IF #SqlLanguage <> ''
SET #SQL = #SQL+' OR U.UserID IN (SELECT UserID FROM Country WHERE LCValues IN ('+ #SqlLanguage +') )'
IF #SqlAreas <> ''
SET #SQL = #SQL+' OR U.UserID IN (SELECT UserID FROM tblAreas WHERE '+#SqlAreas+')'
---------------------Update---------------------------------------
...other filtering condition
EXEC (#SQL)
all filtering condition are implemented with OR logic.
Have you tried implementing a CASE statement to calculate the "Points"?
--in stored procedure i m using dynamic query
DECLARE #SQL VARCHAR(2000)
SET #SQL = '
SELECT
U.[UserID],
U.[StaffNo],
U.[FirstName]+'' ''+ U.[LastName] AS EmployeeName,
(
CASE WHEN EXISTS(SELECT 1 FROM [Country] WHERE /*Your filter comes in here*/) THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT 1 FROM [tblAreas] WHERE /*Your filter comes in here*/) THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT 1 FROM [OtherTable1] WHERE /*Your filter comes in here*/) THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT 1 FROM [OtherTable2] WHERE /*Your filter comes in here*/) THEN 1 ELSE 0 END
) AS Points
FROM [tblUser] U'
SET #SQL = #SQL+' WHERE U.Department in (' + #SqlDepartment + ') OR'...
...other filtering condition
EXEC (#SQL)
I think you might be better off working out the points in your code rather than in the SQL
The only way I can think of doing it is with UNIONS which would be horrible
You can use left outer join to your filter condition, group by UserID to not get duplicates, add a value of 1 for hits and use coalesce to set 0 for no hits.
Some sample code that shows what I mean using Area and Country as filter condition.
declare #U table (UserID int, Name varchar(50), StaffNo char(3), department char(4))
declare #C table (CountryID int, UserID int)
declare #A table (AreaID int, UserID int)
insert into #U values (1, 'KK', '111', 'dep1')
insert into #U values (2, 'NN', '222', 'dep2')
insert into #U values (3, 'DD', '333', 'dep3')
insert into #C values(1, 1)
insert into #C values(2, 1)
insert into #C values(3, 2)
insert into #C values(3, 3)
insert into #A values(1, 1)
insert into #A values(2, 1)
insert into #A values(3, 2)
select
U.UserID,
U.Name,
U.StaffNo,
U.department,
coalesce(C.Point, 0)+coalesce(A.Point,0) as Points
from #U as U
left outer join
(select UserID, 1 as Point
from #C
-- where ...?
group by UserID) as C
on U.UserID = C.UserID
left outer join
(select UserID, 1 as Point
from #A
-- where ...?
group by UserID) as A
on U.UserID = A.UserID
Please help out newbie.
I am reading mothly sales statistics for last two years from stored procedure, display it on asp.net site and it works just fine.
Problem is with products that are not sold often I need to figure out which months do not have any sales. In that case I need to put zero in table cell and move to next row in dataset.
For...Each does not do the trick in case where there isn't data for every month.
Question is, how to move to next sqlrow and how to test when all rows heve been read?
sqlSelect = "EXECUTE dealer_sales_statistics #productID = '" & strProdID.Value & "'"
Dim sqlConn As New SqlConnection(sqlConnStr)
Dim sqlRow As DataRow
sqlConn.Open()
Dim sqlAdapt As New SqlDataAdapter(sqlSelect,sqlConn)
Dim sqlDataSet As New DataSet()
sqlAdapt.Fill(sqlDataSet, "sales_statistics")
Do Until sqlRow.EOF
If intCounter < 12 Then
' arrMonth contains last 24 months, e.g. "12_2009" to "1_2008"'
' stored procedure can return values for any month between that range'
' amount of returned values (DataSet sqlRows) can vary from 0 to 24'
If arrMonth(intCounter) = sqlRow("month") & "_" & sqlRow("year") Then
strLine_1 &= "<td>" & CInt(sqlRow("qty")) & "</td>"
arrSumma_1 = arrSumma_1 + CInt(sqlRow("qty"))
sqlRow.MoveNext
Else
strLine_1 &= "<td class='cell'>0</td>"
End If
Else
'using intCouter and same code to separate sales in 12 month periods'
If arrMonth(intCounter) = sqlRow("month") & "_" & sqlRow("year") Then
strLine_2 &= "<td>" & CInt(sqlRow("qty")) & "</td>"
arrSumma_2 = arrSumma_2 + CInt(sqlRow("qty"))
sqlRow.MoveNext
Else
strLine_2 &= "<td>0</td>"
End If
End If
intCounter = intCounter + 1
Loop
I think that you are focusing on the wrong area by trying to do this in your code. I can think of a likely solution there but it is really messy. Instead, focus on making sure that the sets returned by the stored proc are complete so you can iterate them without worry about missing months. That is, the stored procedure is probably returning sets made up only of months where there were sales (e.g. due to an inner join) - and you need to change this so it returns all months.
So, instead of posting the VB code, I'd suggest that you post the stored proc to get help in resolving the issue.
As a general guideline, I'd approach this by creating a dummy table with the months of the year listed (along with their month numbers to perform the join). Then, fold that table in with the query using a left outer join to ensure that all months are represented. Also, when selecting the final sales figures, make sure that there are no null values (for months where there were no sales) by using an "IsNull(Val, 0) as Val" to substitute a zero.
Again, this is just general guidance, we'd need to see the actual sproc to really help.
Here is how I did solve this with SQL. I create dynamically temp table that holds last 24 months and another temp table with sales data 0 to 24 months. Maybe this will help somebody with similar problem. (code below is in sql server as stored procedure). Thank you for help Mark!
DECLARE #strTemp_months TABLE
(
sorting INT,
months INT,
years INT
)
DECLARE #mnth INT
SET #mnth = 0
WHILE (#mnth < 24)
BEGIN
INSERT #strTemp_months
SELECT CASE WHEN YEAR(GETDATE()) = YEAR(DATEADD( m , -#mnth , GETDATE())) THEN 1 ELSE 2 END AS sorting,
MONTH(DATEADD( m , -#mnth , GETDATE())), YEAR(DATEADD( m , -#mnth , GETDATE()))
SET #mnth = #mnth + 1
END
DECLARE #productID VARCHAR(12)
SET #productID = '1234567890'
DECLARE #strTemp_statistics TABLE
(
sorting INT,
months INT,
years INT,
productno VARCHAR(35),
salesqty DECIMAL(9,2)
)
INSERT #strTemp_statistics
SELECT CASE WHEN YEAR(transaction_date) = YEAR(GETDATE()) THEN 1 ELSE 2 END AS sorting,
MONTH(transaction_date) AS months, YEAR(transaction_date) AS years, product_number AS productno,
SUM(qty) AS salesqty
FROM sales_events
WHERE product_number = #productID
-- including all transactions from last 24 full months until today
AND transaction_date >= CAST(YEAR(DATEADD( m , -23 , GETDATE())) AS CHAR(4)) + '-' + CAST(MONTH(DATEADD( m , -23 , GETDATE())) AS VARCHAR(2)) + '-01'
GROUP BY MONTH(transaction_date), YEAR(transaction_date), product_number
SELECT m.sorting, m.months, m.years, COALESCE(productno, 'No Sales') AS productno, COALESCE(kpl, 0) AS salesqty
FROM #strTemp_months m LEFT OUTER JOIN #strTemp_statistics s
ON m.months = s.months AND m.years = s.years
ORDER BY 1, 2 DESC