update table after ;with() select statement - sql

I use this procedure to select records with paging :
ALTER PROCEDURE [PorSun].[soalPagingByIdGroupIdUser] (
#IdGroup ,
#pageNo int,
#pageSize int)
AS
DECLARE #start int, #end int
SET #start = #pageSize*(#pageNo-1)+1
SET #end= #start+#pageSIze-1
;with Records as
(
SELECT
PorSun.soal.Id, PorSun.soal.IdUser, PorSun.soal.VisitCount
, ROW_NUMBER() over(order by PorSun.soal.Id) as RN
FROM PorSun.soal
WHERE (PorSun.soal.IdGroup=#IdGroup)
)
SELECT Records.Id, Records.IdUser, Records.VisitCount
FROM Records
WHERE RN between #start and #end and (Records.IdGroup=#IdGroup)
ORDER BY Records.Id desc
UPDATE [PorSun].[Soal]
SET [VisitCount] = [VisitCount]+1
WHERE Id IN (SELECT Id FROM Records)
There is no syntax error, but on execute error.
How is it possible?

You can use a table variable instead of a CTE:
DECLARE #Records TABLE
(
Id int,
IdUser int,
VisitCount int,
RN int
)
INSERT INTO #Records
SELECT
PorSun.soal.Id,
PorSun.soal.IdUser,
PorSun.soal.VisitCount,
ROW_NUMBER() over(order by PorSun.soal.Id) as RN
FROM PorSun.soal
WHERE (PorSun.soal.IdGroup=#IdGroup)
SELECT Id, IdUser, VisitCount
FROM #Records
WHERE RN between #start and #end and (IdGroup=#IdGroup)
ORDER BY Id desc
UPDATE [PorSun].[Soal]
SET [VisitCount] = [VisitCount]+1
WHERE Id IN (SELECT Id FROM #Records)

Related

Transaction was deadlocked on lock resources while reading and inserting

normally it works fine (it recalculates time to time production based on daily meter readings , the problem starts when other apps are inserting data into [dbo].[MeterReading] ( at least I belive this is the source of deadlocks), what would you reccomend to avoid exceptions ?
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #ResultVar float;
DECLARE #Val1 TABLE
(
RowID INT IDENTITY ( 1 , 1 ),
InputId int,
TimeStampUtc1 smalldatetime,
Val1 float
);
DECLARE #Val2 TABLE
(
RowID INT IDENTITY ( 1 , 1 ),
InputId int,
TimeStampUtc2 smalldatetime,
Val2 float
);
WITH CTE
AS
(
SELECT [Val],m.InverterInputId, m.[TimeStampUtc]
,ROW_NUMBER() OVER(PARTITION BY m.InverterInputId ORDER BY m.[TimeStampUtc] DESC) AS RN
FROM [dbo].[MeterReading] AS m
inner join InverterInput AS ii on m.InverterInputId = ii.InverterInputId
inner join Inverter AS i on ii.InverterId = i.InverterId
where ii.InputName = 'TotalYield' and i.PlantId = #plantId and m.[TimeStampUtc] >= #from and m.[TimeStampUtc] <= #to
)
INSERT INTO #Val1 (Val1,InputId,TimeStampUtc1 ) Select [Val],[InverterInputId],[TimeStampUtc] FROM CTE WHERE RN = 1;
WITH CTE
AS
(
SELECT [Val],m.InverterInputId, m.[TimeStampUtc]
,ROW_NUMBER() OVER(PARTITION BY m.InverterInputId ORDER BY m.[TimeStampUtc] ASC) AS RN
FROM [dbo].[MeterReading] AS m
inner join InverterInput AS ii on m.InverterInputId = ii.InverterInputId
inner join Inverter AS i on ii.InverterId = i.InverterId
where ii.InputName = 'TotalYield' and i.PlantId = #plantId and m.[TimeStampUtc] >= #from and m.[TimeStampUtc] <= #to
)
INSERT INTO #Val2 (Val2,InputId,TimeStampUtc2) Select [Val],[InverterInputId],[TimeStampUtc] FROM CTE WHERE RN = 1;
--select Val1 , Val2, Val1-Val2 as Result, [#Val1].InputId,[#Val1].TimeStampUtc1,[#Val2].TimeStampUtc2 from #Val1
select Sum(Val1-Val2) as Result from #Val1
inner join #Val2 on [#Val1].InputId = [#Val2].InputId
END

dynamic alias in sql server

I want query field with different alias in stored procedure
select COUNT(EmpCode) as CountEmp+#para
result shoud be
CountEmp1
45
CountEmp2
54
CountEmp1
76
Query loop in c# code:
select COUNT(EmpCode) where something = #something as CountEmp+#para
Approach without dynamic SQL:
--I create temp table for demonstration
DECLARE #some_table TABLE (
Something int,
EmpCode INT
)
INSERT INTO #some_table (Something, EmpCode)
VALUES (1, 10),(1, 22),(1, 12),(2, 12),(2, 30),(3, 65),(3, 15),(3, 11),(3, 5)
--Declare parameter we want to search
DECLARE #param int = 1
--Query
--In cte we select what we need based on parameter
;WITH cte AS (
SELECT 'CountEmp'+CAST(#param as nvarchar(10)) as SomeThing,
CAST(COUNT(EmpCode) as nvarchar(10)) as EmpCodeCount,
ROW_NUMBER() OVER (ORDER BY SomeThing ) as rn
FROM #some_table
WHERE SomeThing = #param
GROUP BY SomeThing
)
--And here comes UNION
SELECT SomeThing as Result
FROM (
SELECT SomeThing,rn
FROM cte
UNION ALL
SELECT EmpCodeCount ,rn
FROM cte
) as t
ORDER BY rn, SomeThing DESC
Output:
Result
------------------
CountEmp1
3
(2 row(s) affected)
Please try to make use of below code. Its working fine with SQL Server 2012.
IF OBJECT_ID ('temp..#Mytable') IS NOT NULL
CREATE TABLE #Mytable (ID INT IDENTITY (1,1),EmpCode INT)
DECLARE #max int ,#count int
SET #max =0;
DECLARE #str varchar(10)
INSERT #Mytable
(EmpCode)
VALUES
(10),
(45),
(35),
(63),
(56),
(65)
SET #count = (SELECT COUNT (ID) FROM #Mytable )
WHILE #count > #max
BEGIN
SET #max = #max+1
SET #str = CONVERT(varchar(10),#max)
EXEC('SELECT EmpCode AS Empcode'+#str+ ' FROM #Mytable WHERE ID = '+#str)
END

Getting data for a user in a month

(The database is Postgres )
Let's say I have a table races with columns (user_name , race_time , race_speed , race_no).
Each users can have multiple races . I want to get data for each month and show for each month how many races are played in that month. But I also want to show which user played the most and which played has the maximum speed.
select
extract ( month from race_time) as month,
extract ( year from race_time) as year,
count(race_no) as total_races
from races r
group by year,month
order by year desc,month desc
The above query gives me each month and the total races but how can I find for each month which user played the most (that'd be one user)?
I hope someone could help me with this.
SQL Fiddle
with r as (
select
to_char(race_time, 'YYYY-MM') as month,
user_name,
count(*) as n_races,
max(race_speed) as max_speed
from races
group by 1, 2
), total_races as (
select sum(n_races) as total_races, month
from r
group by month
)
select *
from (
select distinct on (month)
month, user_name as user_most_races, n_races as most_races
from r
order by 1, 3 desc
) s
inner join (
select distinct on (month)
month, user_name as user_max_speed, max_speed
from r
order by 1, 3 desc
) q using (month)
inner join
total_races using(month)
order by month
SELECT COUNT(DISTINCT user_name), user_name, EXTRACT(month FROM race_time) AS month, EXTRACT(year FROM race_time) AS year
FROM races r
GROUP BY user_name, year, month
ORDER BY year desc, month desc
Try it!
USE [DATABASE_NAME]
GO
--this is calculating the which user played the most
CREATE FUNCTION [dbo].[GetHighestPlayedRaceUserByYearMonth]
(
-- Add the parameters for the function here
#Year INT, #Month INT
)
RETURNS NVARCHAR(50)
AS
BEGIN
-- Declare the return variable here
DECLARE #UserName NVARCHAR(50)
-- Add the T-SQL statements to compute the return value here
DECLARE #TempTbl TABLE(Played INT,UserName NVARCHAR(50))
INSERT INTO #TempTbl(Played,UserName)
SELECT
COUNT(race_no) AS Played,
[user_name] AS UserName
FROM Table_1
WHERE
YEAR(race_time)=#Year and
MONTH(race_time)=#Month
GROUP BY
MONTH(race_time),
YEAR(race_time),
[user_name]
ORDER BY
YEAR(race_time) DESC,
MONTH(race_time) DESC,
COUNT(race_no) DESC
DECLARE #MaxPlayed INT
SET #MaxPlayed=(SELECT TOP 1 Played FROM #TempTbl ORDER BY Played DESC)
DECLARE #TempTbl2 TABLE(ID INT IDENTITY(1,1) NOT NULL,UserName NVARCHAR(50))
INSERT INTO #TempTbl2
SELECT UserName FROM #TempTbl WHERE Played=#MaxPlayed
DECLARE #ROWCOUNT INT
SET #ROWCOUNT=1
SET #UserName=''
WHILE (SELECT COUNT(*) FROM #TempTbl2)>=#ROWCOUNT
BEGIN
IF (SELECT COUNT(*) FROM #TempTbl2)=#ROWCOUNT
BEGIN
SET #UserName= #UserName+(SELECT UserName FROM #TempTbl2 WHERE ID=#ROWCOUNT)
END
ELSE
BEGIN
SET #UserName= #UserName+(SELECT UserName FROM #TempTbl2 WHERE ID=#ROWCOUNT)+','
END
SET #ROWCOUNT=#ROWCOUNT+1
END
-- Return the result of the function
RETURN #UserName
END
GO
--this is calculating which user played with the maximum speed
CREATE FUNCTION [dbo].[GetMaxRaceSpeedUserByYearMonth]
(
-- Add the parameters for the function here
#Year INT, #Month INT
)
RETURNS NVARCHAR(50)
AS
BEGIN
-- Declare the return variable here
DECLARE #UserName NVARCHAR(50)
-- Add the T-SQL statements to compute the return value here
DECLARE #TempTbl TABLE(MaxRaceSpeed INT,UserName NVARCHAR(50))
INSERT INTO #TempTbl(MaxRaceSpeed,UserName)
SELECT
MAX(race_speed) AS MaxRaceSpeed,
[user_name] AS UserName
FROM Table_1
WHERE
YEAR(race_time)=#Year and
MONTH(race_time)=#Month
GROUP BY
MONTH(race_time),
YEAR(race_time),
[user_name]
ORDER BY
YEAR(race_time) DESC,
MONTH(race_time) DESC,
COUNT(race_no) DESC
DECLARE #MaxRaceSpeed INT
SET #MaxRaceSpeed=(SELECT TOP 1 MaxRaceSpeed FROM #TempTbl ORDER BY MaxRaceSpeed DESC)
DECLARE #TempTbl2 TABLE(ID INT IDENTITY(1,1) NOT NULL,UserName NVARCHAR(50))
INSERT INTO #TempTbl2
SELECT UserName FROM #TempTbl WHERE MaxRaceSpeed=#MaxRaceSpeed
DECLARE #ROWCOUNT INT
SET #ROWCOUNT=1
SET #UserName=''
WHILE (SELECT COUNT(*) FROM #TempTbl2)>=#ROWCOUNT
BEGIN
IF (SELECT COUNT(*) FROM #TempTbl2)=#ROWCOUNT
BEGIN
SET #UserName= #UserName+(SELECT UserName FROM #TempTbl2 WHERE ID=#ROWCOUNT)
END
ELSE
BEGIN
SET #UserName= #UserName+(SELECT UserName FROM #TempTbl2 WHERE ID=#ROWCOUNT)+','
END
SET #ROWCOUNT=#ROWCOUNT+1
END
-- Return the result of the function
RETURN #UserName
END
GO
--Select Query
SELECT
MONTH(race_time) AS [Month],
YEAR(race_time) AS [Year],
COUNT(race_no) AS RacePlayed,
dbo.GetHighestPlayedRaceUserByYearMonth(YEAR(race_time),MONTH(race_time)) AS MaximunPlayedUser,
dbo.GetMaxRaceSpeedUserByYearMonth(YEAR(race_time),MONTH(race_time)) AS MaximunSpeedUser
FROM TABLE_NAME
GROUP BY MONTH(race_time),YEAR(race_time)
ORDER BY YEAR(race_time) DESC,MONTH(race_time) DESC

Selecting Spicific data placed in the middle of the database table

how to determine which row number in my database will the selection query start to select and the Limit of the selection ,as I want to select piece of data which is located in the middle of my database table
I may use between #indexOfSelection , #limitOfSelection or something like that ,but I don't know how !
CREATE PROCEDURE ordered_articles
#LowerBound int,
#UpperBound int
AS
select * from orderedData where articleid between LowerBound and UpperBound ;
with orderedData
(
select * , rn = ROW_NUMBER() over ORDER BY (articleid)
from articles
)
WHERE rn >= #LowerBound AND rn <= #UpperBound
RETURN
I guess you can make use of ROW_NUMBER Function something like this ....
;WITH OrderedData
AS
(
SELECT * , rn = ROW_NUMBER() OVER (ORDER BY SomeColumn)
FROM Table_Name
)
SELECT * FROM OrderedData
WHERE rn >= #LowerLimit AND rn <= #UpperLimit
Your Query
select * from articles
where articleid between #indexOfSelection AND #LimitOfselection
You just need to add the key word AND between your upper lower limit variable and upper limit variable.
Your Stored Procedure
CREATE PROCEDURE ordered_articles
#LowerBound int,
#UpperBound int
AS
BEGIN
SET NOCOUNT ON;
select * from articles
where articleid between #LowerBound and #UpperBound
END
To Select A range Of Rows
CREATE PROCEDURE ordered_articles
#LowerBound int,
#UpperBound int
AS
BEGIN
SET NOCOUNT ON;
WITH OrderedData
AS
(
SELECT * , rn = ROW_NUMBER() OVER (ORDER BY articleid)
FROM articles
)
SELECT * FROM OrderedData
WHERE rn >= #LowerBound AND rn <= #UpperBound
END
EXECUTE ordered_articles 10, 15 --<-- this will return 10 to 15 number row ordered by ArticleID

Select TOP 2 results in variables without loop

I want to store the top 2 results in 2 variables.
create table t(id int);
insert into t (id) values (1),(2),(3),(4);
declare #id1 int
declare #id2 int
select top 2 #id1 = first id,
#id2 = next id
from t
SQLFiddle
Can I do it in one query without using a loop?
declare #id1 int,#id2 int
;with cte as (
select top (2) id
from t
order by id
)
select #id1 = min(id), #id2 = max(id)
from cte
select #id1,#id2
Fiddle demo
with cte as (
select top 2 id, row_number() over(order by id) as rn
from t
order by id
)
select
#id1 = (select id from cte where rn = 1),
#id2 = (select id from cte where rn = 2)
or
with cte as (
select top 2 id, row_number() over(order by id) as rn
from t
order by id
)
select
#id1 = max(case when rn = 1 then id end),
#id2 = max(case when rn = 2 then id end)
from cte
sql fiddle demo
You can use LEAD() for SQL Server 2012.
SELECT TOP 1 #id1 = ID, #id2 = LEAD(ID) OVER (ORDER BY ID) FROM t
SQLFiddle Demo
With two SELECT it's easy...
DECLARE #id1 INT
DECLARE #id2 INT
SELECT TOP 1 #id1 = x.id
FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY id) RN FROM t) x
WHERE x.RN = 1
SELECT TOP 1 #id2 = x.id
FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY id) RN FROM t) x
WHERE x.RN = 2
SELECT #id1, #id2
With SQL 2012 you clearly could
SELECT #id1 = id
FROM t ORDER BY id OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
SELECT #id2 = id
FROM t ORDER BY id OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY
Or evein in 2008 you could
; WITH Base AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) RN FROM t
)
SELECT #id1 = b1.id, #id2 = b2.id
FROM Base b1, Base b2
WHERE b1.RN = 1 AND B2.RN = 2
declare #id1 int
declare #id2 int
declare #table table(id int,rownum int)
insert into #table
select top 2 id,row_number() over( order by id) as rn from t
select #id1=case rownum when 1 then id else #id1 end,
#id2=case rownum when 2 then id end from #table
select #id1,#id2
SQL FIDDLE
More easy way with 2 selects:
declare #id1 int
declare #id2 int
select top 1 #id1 = id from t
select top 2 #id2 = id from t
select #id1, #id2
SQL Fiddle