I want to make a custom paging according to the following link:
but my stored procedure is in informix:
so I search for the equivalent row_number() I find this solution
but when I use it in my procedure I get the following error:
SQL error -944 Cann't use "first","limit","skip" in this context !
How to rewrite the stored procedure in the previous link with informix rules?
my procedure has multiple unions is like this:
create procedure get_inbox_page(p_emp_num smallint, p_task_code smallint, p_main_code smallint default 0, p_year smallint default 0,p_page int)
returning varchar(60) as v_page_view, varchar(60) as v_task_name, smallint as v_task_code, varchar(60) as v_sp_name, varchar(60) as v_db_name, varchar(60) as v_column_key, smallint as v_trans_serial,
DATETIME YEAR TO FRACTION(3) as v_trans_date, varchar(60) as v_trans_desc , varchar(60) as v_emp_name, varchar(60) as v_values_key, smallint as v_old_state_serial,
smallint as v_new_state_serial, smallint as v_main_code, smallint as v_year, varchar(60) as v_page_new, smallint as v_task_type, smallint as v_task_status,smallint as v_mail_maincode,smallint as v_mail_year,smallint as v_mail_number,smallint as v_trans_year , smallint as candidate_flag ;
Select ......
UNION
Select ......
UNION
Select ......
You cannot use FIRST, SKIP etc, because each SELECT statement within the UNION collection is self-contained.
Perhaps you could try creating a VIEW that encapsulates the SELECT ... UNION ... SELECT logic, and then apply the FIRST/SKIP logic to that.
try this
;
WITH tempPagedRecord
AS ( SELECT Column1 ,
Column2 ,
Column3
FROM TableName AS e--Your query with union
UNION ALL
SELECT Column1 ,
Column2 ,
Column3
FROM TableName AS e--Your query with union
)
SELECT * ,
ROW_NUMBER() OVER ( ORDER BY Column1 ASC ) AS RowNumber--RowNumber over some column
FROM tempPagedRecord
WHERE RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
Related
I am creating a database in SSMS and I am trying to calculate AVG from 2 columns from 2 tablets; I wrote :
;WITH combined AS
(
SELECT Datum_narodenia
FROM Zamestnanci
UNION ALL
SELECT Datum_narodenia
FROM ObčaniaSR
)
SELECT AVG(Datum_narodenia)
FROM combined;
But I got this error:
Msg 8117, Level 16, State 1Operand data type date is invalid for avg operator.
I created table 1 :
CREATE TABLE Zamestnanci
(
id_Zamestnanca int not null,
Meno varchar(50) null,
Priezvisko varchar(50)null,
Adresa varchar(50) null,
Datum_narodenia date null,
PRIMARY KEY (id_Zamestnanca)
);
CREATE TABLE ObčaniaSR
(
id_Občana int not null,
Meno varchar(50) null,
Priezvisko varchar(50) null,
Adresa varchar(50) null,
Datum_narodenia date null,
Zápis_v_trestnom_registry varchar(50) null,
PRIMARY KEY (id_Občana)
);
Datum_narodenia means Date_of_birth from witch I try to calculate AVG.
What is best way to calculate AVG age according to you? Thank you for your answers and advice.
Pretty close calculation of age (lots of nitty-gritty in this answer) uses the difference in hours between the date and now, divided by the number of hours in a year (8766/24 = 365.25), which tries to roughly account for leap years; it is imperfect, but a pretty good trade-off IMHO between simple and right:
SELECT DATEDIFF(HOUR,'19860201',GETDATE())/8766;
So:
;WITH combined AS
(
SELECT Datum_narodenia
FROM Zamestnanci
UNION ALL
SELECT Datum_narodenia
FROM ObčaniaSR
)
SELECT AVG(DATEDIFF(HOUR, Datum_narodenia, GETDATE())/8766)
FROM combined;
Now, this does integer math, so you might instead want:
;WITH combined AS
(
SELECT Datum_narodenia
FROM Zamestnanci
UNION ALL
SELECT Datum_narodenia
FROM ObčaniaSR
)
SELECT CONVERT(DECIMAL(5,1),
AVG(DATEDIFF(HOUR, Datum_narodenia, GETDATE())/8766.0))
FROM combined;
I want to achieve an auto increment ID with prefix but resetting the number if it has different prefix.
The output I want looks like this:
ID PREFIX PROJECTID
1 PID_ PID_1
2 PID_ PID_2
3 RID_ RID_1
4 RID_ RID_2
But the result I got with my script is this:
ID PREFIX PROJECTID
1 PID_ PID_1
2 PID_ PID_2
3 RID_ RID_3
4 RID_ RID_4
Here's my script to create the table
CREATE TABLE PROJECTS
(ID INT IDENTITY(1,1) NOT NULL,
PREFIX NVARCHAR(10) NOT NULL,
PROJECTID AS ISNULL(PREFIX + CAST(ID AS NVARCHAR(10)), '') PERSISTED)
INSERT INTO PROJECTS(PREFIX) VALUES('PID_'),('PID_'),('RID_'),('RID_')
I'm using MS SQL 2012
you want like this
CREATE TABLE #PROJECTS
(
ID INT IDENTITY(1, 1)
NOT NULL ,
PREFIX NVARCHAR(10) NOT NULL ,
PROJECTID NVARCHAR(11)
)
INSERT INTO #PROJECTS
( PREFIX )
VALUES ( 'PID_' ),
( 'PID_' ),
( 'RID_' ),
( 'RID_' )
suppose you have above data in your table
now if you want to perform insert with DECLARE #PREFIX NVARCHAR(10) = 'RID_'
INSERT INTO #PROJECTS
( PREFIX ,
PROJECTID
)
SELECT #PREFIX ,
#PREFIX + CAST(( COUNT(TT.rn) + 1 ) AS NVARCHAR(1))
FROM ( SELECT ROW_NUMBER() OVER ( PARTITION BY P.PREFIX ORDER BY ( SELECT
NULL
) ) AS rn
FROM #PROJECTS AS P
WHERE P.PREFIX = #PREFIX
) AS tt
see above query may helps you.
Hi i found the ansowr after working couple of hours in Ms Sql server
USE [StocksDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tb1_triger]
ON [dbo].[Table1]
instead of INSERT
AS
declare #name nchar(12)
select top 1 #name=name from inserted
declare #maxid char(12)
select #maxid = MAX(id1) from Table1
BEGIN
SET NOCOUNT ON;
if (#maxid is null)
begin
set #maxid=0
end
set #maxid= substring(#maxid, 5 , LEN(#maxid))+1
INSERT INTO table1
(id1,name) SELECT CONCAT_WS((REPLICATE('0',12-4-LEN(#maxid))),'tblo',#maxid),i.name
from inserted i
END
You can do this with an INSTEAD OF trigger on the table rather than using a PERSISTED column. I have written the trigger so that it will correctly handle bulk inserts as this is something many people overlook. Also, for my solution it is not necessary to have an IDENTITY column on the table if you do not want it.
So the table has been defined with the column included. Also, you can get rid of the IDENTITY column as I mentioned above:
CREATE TABLE dbo.PROJECTS
(
ID INT IDENTITY(1, 1) NOT NULL,
PREFIX NVARCHAR(10) NOT NULL,
PROJECTID NVARCHAR(20) NOT NULL
);
One note - since the PREFIX column is NVARCHAR(10) and I do not know how big the numbers will get, the size of the PROEJCTID column was increased to prevent overflow. Adjust the size as your data requires.
Here is the trigger:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER dbo.InsertProjects
ON dbo.PROJECTS
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #rowsAffected INT = (SELECT COUNT(*) FROM Inserted);
-- if there are no rows affected, no need to do anything
IF #rowsAffected = 0 RETURN;
DECLARE #ExistingCounts TABLE (
Prefix NVARCHAR(10) NOT NULL,
ExistingCount INT NOT NULL
);
-- get the count for each existing prefix
INSERT INTO #ExistingCounts(Prefix, ExistingCount)
SELECT PREFIX, COUNT(*) FROM dbo.PROJECTS GROUP BY PREFIX;
-- since this is an INSTEAD OF trigger, we must do the insert ourself.
-- a prefix might not exist, so use ISNULL() to get a zero in that case.
INSERT INTO dbo.PROJECTS
(
PREFIX, PROJECTID
)
SELECT sub.PREFIX,
-- the number after the prefix is the existing count for the prefix plus
-- the position of the prefix in the Inserted table
sub.PREFIX + CAST((sub.ExistingCount + sub.Number) AS NVARCHAR(10))
FROM
(SELECT i.PREFIX,
-- get the position (1, 2, 3...) of the prefix in the Inserted table
ROW_NUMBER() OVER(PARTITION BY i.PREFIX ORDER BY i.PREFIX) AS [Number],
-- get the existing count of the prefix
ISNULL(c.ExistingCount, 0) AS [ExistingCount]
FROM Inserted AS i
LEFT OUTER JOIN #ExistingCounts AS c ON c.Prefix = i.PREFIX) AS sub;
END
GO
I have included comments in the source code to explain the simple logic. Hopefully this helps and is what you are looking for :-)
Hey use this query..
CREATE FUNCTION DBO.GET_NEX_P_ID(#PREF VARCHAR(4))
RETURNS NVARCHAR(24)
AS
BEGIN
RETURN (SELECT #PREF+CAST(COUNT(1)+1 AS VARCHAR) FROM PROJECTS WHERE PREFIX=#PREF)
END
GO
CREATE TABLE PROJECTS
(
PREFIX VARCHAR(8),
PROJECTID NVARCHAR(24)
)
GO
INSERT INTO PROJECTS
VALUES('PRJ_',DBO.GET_NEX_P_ID('PRJ_'))
GO
INSERT INTO PROJECTS
VALUES('PRQ_',DBO.GET_NEX_P_ID('PRQ_'))
GO
Thanks
My Table:
CREATE TABLE USER_DATA
([ID] NVARCHAR(10),[NAME] NVARCHAR(50))
My Stored Procedure:
CREATE PROC SP_INSERT_USER
#NAME VARCHAR(50)
AS
BEGIN
DECLARE #ID NVARCHAR(50)
DECLARE #IDTEMP INT
SELECT #IDTEMP=MAX(CAST(RIGHT([ID],3) AS INT) ) FROM USER_DATA
SELECT #IDTEMP=CASE WHEN #IDTEMP IS NULL THEN 1 ELSE #IDTEMP+1 END
SELECT #ID='RP'+RIGHT(('000'+CAST(#IDTEMP AS VARCHAR(10))),3)
INSERT INTO USER_DATA VALUES (#ID,#NAME)
END
Input:
SP_INSERT_USER 'Ajit'
SP_INSERT_USER 'Amit'
Output:
ID NAME
---------- --------------------------------------------------
RP001 Ajit
RP002 Amit
This code is working fine. But the ID is fixed. It is limited to 3 digits like 001, 002, etc. If it get 1000th employee, it is not displaying properly. Is there any way to make it dynamical without fixing the length?
Try this one -
CREATE TABLE dbo.USER_DATA
(
PK INT IDENTITY(1,1) PRIMARY KEY
, ID AS 'PR' + RIGHT('00' + CAST(PK AS VARCHAR(5)), 5)
, NAME NVARCHAR(50)
)
GO
CREATE PROC dbo.SP_INSERT_USER
#NAME VARCHAR(50)
AS BEGIN
INSERT INTO dbo.USER_DATA
VALUES (#NAME)
END
GO
EXEC dbo.SP_INSERT_USER 'Ajit'
EXEC dbo.SP_INSERT_USER 'Amit'
SELECT ID, NAME
FROM dbo.USER_DATA
I am trying to update a data set based on one conditional and then retrieving all the updated rows. VS keeps telling me there is an incorrect syntax error near my OUTPUT clause but I do not see anything wrong. I am just trying to figure out how to use "OUTPUT" so this may be a very stupid mistake I am making but failing to see.
What is wrong (syntactically) with this OUTPUT clause?
CREATE PROCEDURE [dbo].[GetInitialSessionNotifications]
#CurrentSessionId bigint
AS
DECLARE #tempTable table(
id bigint NOT NULL,
[Type] nvarchar,
DocumentCommentID bigint,
AnnouncmentID int,
EventID int,
MeetingID int,
[Read] bit,
RecieverId int,
AnnouncmentCommentId bigint,
EventCommentId bigint,
MeetingCommentId bigint,
DateAndTime DateTime);
UPDATE Notifications SET SessionId = #CurrentSessionId
WHERE SessionId != #CurrentSessionId
OUTPUT INSERTED.id,
INSERTED.[Type],
INSERTED.DocumentCommentID,
INSERTED.AnnouncmentID,
INSERTED.EventID,
INSERTED.MeetingID,
INSERTED.[Read],
INSERTED.RecieverId,
INSERTED.AnnouncmentCommentId,
INSERTED.EventCommentId,
INSERTED.MeetingCommentId,
INSERTED.DateAndTime
INTO #tempTable;
SELECT id, [Type], DocumentCommentId, AnnouncmentID, EventID, MeetingID,
[Read], RecieverId, AnnouncmentCommentId, EventCommentId, MeetingCommentId, DateAndTime
FROM #tempTable;
RETURN 0
Try this one -
CREATE PROCEDURE [dbo].[GetInitialSessionNotifications]
#CurrentSessionId BIGINT
AS BEGIN
DECLARE #tempTable TABLE
(
id BIGINT NOT NULL ,
[Type] NVARCHAR ,
DocumentCommentID BIGINT ,
AnnouncmentID INT ,
EventID INT ,
MeetingID INT ,
[Read] BIT ,
RecieverId INT ,
AnnouncmentCommentId BIGINT ,
EventCommentId BIGINT ,
MeetingCommentId BIGINT ,
DateAndTime DATETIME
)
UPDATE Notifications
SET SessionId = #CurrentSessionId
OUTPUT
INSERTED.id ,
INSERTED.[Type] ,
INSERTED.DocumentCommentID ,
INSERTED.AnnouncmentID ,
INSERTED.EventID ,
INSERTED.MeetingID ,
INSERTED.[Read] ,
INSERTED.RecieverId ,
INSERTED.AnnouncmentCommentId ,
INSERTED.EventCommentId ,
INSERTED.MeetingCommentId ,
INSERTED.DateAndTime
INTO #tempTable
WHERE SessionId != #CurrentSessionId
SELECT id ,
[Type] ,
DocumentCommentId ,
AnnouncmentID ,
EventID ,
MeetingID ,
[Read] ,
RecieverId ,
AnnouncmentCommentId ,
EventCommentId ,
MeetingCommentId ,
DateAndTime
FROM #tempTable;
END
I have one source table that should be converted to one destination table. The source table contains four columns with sensor values. The destination table should contain four rows with the single sensor value and with one column for number of the sensor -- for each row from the source table. In other words, the destination table will have four times more rows. (I believe this is called normalization. At least, I think it will be more practical in future when more or less or different sensors are to be used.)
More background information to explain. I have already successfully tried an insert trigger that does that for a single line:
CREATE TRIGGER dbo.temperatures_to_sensors
ON dbo.Data
AFTER INSERT
AS
BEGIN
DECLARE #line_no TINYINT;
SET #line_no = 2; -- hardwired for the production line
DECLARE #UTC DATETIME;
DECLARE #value1 FLOAT;
DECLARE #value2 FLOAT;
DECLARE #value3 FLOAT;
DECLARE #value4 FLOAT;
SELECT
#UTC = CAST((CAST(LEFT(inserted.UTC, 16) AS FLOAT) - 2415020.5) AS DATETIME),
#value1 = inserted.temperature_1,
#value2 = inserted.temperature_2,
#value3 = inserted.temperature_3,
#value4 = inserted.temperature_4
FROM inserted;
INSERT INTO dbo.line_sensor_values
(UTC, line_no, sensor_no, sensor_value)
VALUES (#UTC, #line_no, 1, #value1),
(#UTC, #line_no, 2, #value2),
(#UTC, #line_no, 3, #value3),
(#UTC, #line_no, 4, #value4);
END;
GO
Now, I would like to initialize the destination table from the old table once. After that, the trigger will continue to fill the values.
I am not good in SQL. I tried:
CREATE PROCEDURE dbo.init_line_sensor_values
AS
BEGIN
DECLARE #line_no TINYINT;
SET #line_no = 2; -- hardwired for the production line
DECLARE #UTC DATETIME;
DECLARE #value1 FLOAT;
DECLARE #value2 FLOAT;
DECLARE #value3 FLOAT;
DECLARE #value4 FLOAT;
INSERT INTO dbo.line_sensor_values
(UTC, line_no, sensor_no, sensor_value)
VALUES (#UTC, #line_no, 1, #value1),
(#UTC, #line_no, 2, #value2),
(#UTC, #line_no, 3, #value3),
(#UTC, #line_no, 4, #value4)
SELECT
#UTC = CAST((CAST(LEFT(t.UTC, 16) AS FLOAT) - 2415020.5) AS DATETIME),
#value1 = t.temperature_1,
#value2 = t.temperature_2,
#value3 = t.temperature_3,
#value4 = t.temperature_4
FROM dbo.Data AS t;
END;
GO
EXECUTE dbo.init_line_sensor_values
GO
... but it fails with
Cannot insert the value NULL into column 'UTC', table '1000574.dbo.line_sensor_values'; column does not allow nulls. INSERT fails.
It is apparent that the SELECT should be used differently to feed the INSERT. Or do I have to use the loop? (Cursor created and FETCH NEXT... and WHILE...)
UPDATED
The source table can be created this way (simplified):
CREATE TABLE dbo.Data(
UTC varchar(32) NOT NULL,
temperature_1 float NULL,
temperature_2 float NULL,
temperature_3 float NULL,
temperature_4 float NULL
PRIMARY KEY CLUSTERED
(
UTC ASC
)
GO
The destination table was created this way:
CREATE TABLE dbo.line_sensor_values (
UTC DATETIME NOT NULL,
line_no TINYINT NOT NULL, -- line number: 1, 2, 3, etc.
sensor_no TINYINT NOT NULL, -- sensor number: 1, 2, 3, etc.
sensor_value float NULL, -- the measured value
PRIMARY KEY CLUSTERED (
UTC ASC,
line_no ASC,
sensor_no ASC
)
)
GO
Thanks for your help, Petr
If all you need to do is to convert a table with four columns into a single table where each row represents a row number from a source table and a column from a source table, then here is an example:
Here is SQLFiddle
create table fourColumns
(
column1 varchar(50),
column2 varchar(50),
column3 varchar(50),
column4 varchar(50)
)
insert into fourColumns select 'A','B','C','D'
insert into fourColumns select 'E','F','G','H'
;with MyCTE (lineNumber, columnNumber, Result)
as
(
select ROW_NUMBER() OVER(ORDER BY column1 ASC) AS Row, 1, column1
from fourColumns
union all
select ROW_NUMBER() OVER(ORDER BY column2 ASC) AS Row, 2, column2
from fourColumns
union all
select ROW_NUMBER() OVER(ORDER BY column3 ASC) AS Row, 3, column3
from fourColumns
union all
select ROW_NUMBER() OVER(ORDER BY column4 ASC) AS Row, 4, column4
from fourColumns
)
-- add insert here
select lineNumber,
columnNumber,
Result
from MyCTE
order by lineNumber
INSERT INTO dbo.line_sensor_value
(UTC, line_no, sensor_no, sensor_value)
select UTC, line_no, sensor_no, temperature_1 as sensor_value from dbo.Data
union
select UTC, line_no, sensor_no, temperature_2 as sensor_value from dbo.Data
union
select UTC, line_no, sensor_no, temperature_3 as sensor_value from dbo.Data
union
select UTC, line_no, sensor_no, temperature_4 as sensor_value from dbo.Data