I'm dusting off my SQL (or in this case TSQL) and have been writing a stored procedure. Up to this point in my code I can get fine execution with LINQPad as I test my code on the side. However, this particular block, where I have the top scores for each user added to temporary table #QuizScores is delivering a generic syntax error
Incorrect syntax near the keyword 'SELECT'
I've tried to move all the pieces of this statement around but seem to be failing. Any insight you might be able to share?
Here's the statement:
SELECT *
INTO #QuizScores
FROM (SELECT ROW_NUMBER()
OVER (
PARTITION BY UserID
ORDER BY count(#QuizResponses.IsCorrectAnswer) DESC) AS
RowNumber,
UserID,
count(#QuizResponses.IsCorrectAnswer) AS
Points
FROM #QuizResponses)
JOIN #QuizResponses
ON #QuizResponses.QuizAttemptID = #QuizAttemptList.QuizAttemptID;
i have taken some assumed data inserted into temp table and modified syntax according to your requirement
IF OBJECT_ID('tempdb..#QuizResponses') IS NOT NULL
DROP TABLE #QuizResponses
GO
IF OBJECT_ID('tempdb..#QuizScores') IS NOT NULL
DROP TABLE #QuizScores
CREATE TABLE #QuizResponses (UserId int,correctanswer int,IsCorrectAnswer varchar(1),QuizAttemptID INT)
INSERT INTO #QuizResponses (UserId,correctanswer,IsCorrectAnswer)values (1,1,'Y',2),(2,1,'N',2)
select P.RowNumber,P.Points,P.UserId INTO #QuizScores from (
SELECT ROW_NUMBER() OVER (PARTITION BY a.UserID
ORDER BY count(a.IsCorrectAnswer) DESC) AS RowNumber, a.UserID ,
count(a.IsCorrectAnswer) AS Points
FROM #QuizResponses a
JOIN #QuizResponses S ON S.UserId = A.UserId
group by a.UserId )P
[EDIT: This reflects an earlier revision of the question.]
From MSDN:
SELECT…INTO creates a new table in the default filegroup
Emphasis added.
Related
I have an exercise in SQL Server: I have two tables Country and Events.
The Events table holds the event details including the city where an event happens. The table Events has a foreign key CountryID (CountryID is the primary key in table Country).
I need to create a temporary table showing the most eventful country for each year.
Any help would be appreciated
Thanks
You weren't far off with your attempt, but you need to use a CTE to aggregate your data first. I've assumed that the final order of your data is important, so I used a second CTE, rather than a TOP 1 WITH TIES tio get the final result:
WITH CTE AS(
SELECT YEAR(e.EventDate) AS YearOfEvent,
c.CountryName,
COUNT(e.CountryID) AS NumberOfEvents
FROM [dbo].[tblEvent] AS e
INNER JOIN tblCountry AS c ON e.CountryID = c.CountryID
GROUP BY e.CountryId,
c.CountryName,
YEAR(e.EventDate)),
RNs AS(
SELECT YearOfEvent,
CountryName,
NumberOfEvents,
ROW_NUMBER() OVER (PARTITION BY YearOfEvent ORDER BY CTE.NumberOfEvents DESC) AS RN
FROM CTE)
SELECT YearOfEvent,
CountryName,
NumberOfEvents
FROM RNs
WHERE RN = 1
ORDER BY RNs.YearOfEvent ASC;
I have two tables
1- Table of TestModules
TestModules
2- Table of TestModule_Results
TestModule_Results
in order to get the required information for each TestModule, I am using FULL OUTER JOIN and it works fine.
FULL OUTER JOIN result
But what is required is slightly different. The above picture shows that TestModuleID = 5 is listed twice, and the requirement is to list the 'up-to-date' results based on time 'ChangedAt'
Of course, I can do the following:
SELECT TOP 1 * FROM TestModule_Results
WHERE DeviceID = 'xxx' and TestModuleID = 'yyy'
ORDER BY ChangedAt DESC
But this solution is for a single row and I want to do it in a Stored Procedure.
Expected output should be like:
ExpectedOutput
Any advise how can I implement it in a SP?
Use a Common Table Expression and Row_Number to add a field identifying the newest results, if any, and select for just those
--NOTE: a Common Table Expression requires the previous command
--to be explicitly terminiated, prepending a ; covers that
;WITH cteTR as (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY DeviceID, TestModuleID
ORDER BY ChangedAt DESC) AS ResultOrder
FROM TestModule_Results
--cteTR is now just like TestModule_Results but has an
--additional field ResultOrder that is 1 for the newest,
--2 for the second newest, etc. for every unique (DeviceID,TestModuleID) pair
)
SELECT *
FROM TestModules as M --Use INNER JOIN to get only modules with results,
--or LEFT OUTER JOIN to include modules without any results yet
INNER JOIN cteTR as R
ON M.DeviceID = R.DeviceID AND M.TestModuleID = R.TestModuleID
WHERE R.ResultOrder = 1
-- OR R.ResultOrder IS NULL --add if Left Outer Join
You say "this solution is for a single row"? Excellent. Use CROSS APPLY and change the WHERE clause from hand-input literal to the fields of the original table. APPLY operates at row level.
SELECT *
FROM TestModules t
CROSS APPLY
(
SELECT TOP 1 * FROM TestModule_Results
WHERE TestModule_Results.DeviceID = TestModules.DeviceID -- put the connecting fields here
ORDER BY ChangedAt DESC
)tr
I have to write an SELECT INTO T-SQL script for a table which has columns acc_number, history_number and note.
How do i facilitate an incremental value of history_number for each record being inserted via SELECT INTO.
Note, that the value for history_number comes off as a different value for each account from a different table.
SELECT history_number = IDENTITY(INT,1,1),
... etc...
INTO NewTable
FROM ExistingTable
WHERE ...
You could use ROW_NUMBER instead of identity i.e. ROW_NUMBER() OVER (ORDER BY )
SELECT acc_number
,o.historynumber
,note
,o.historynumber+DENSE_RANK() OVER (Partition By acc_number ORDER BY Note) AS NewHistoryNumber
--Or some other order by probably a timestamp...
FROM Table t
INNER JOIN OtherTable o
ON ....
Working Fiddle
The will give you an incremented count starting from history number for each accnum. I suggest you use a better order by in the rank but there was not enough info in the question.
This answer to this question may help you as well
Question
Suppose your SELECT statement is like this
SELECT acc_number,
history_number,
note
FROM [Table]
Try this Query as below.
SELECT ROW_NUMBER() OVER (ORDER BY acc_number) ID,
acc_number,
history_number,
note
INTO [NewTable]
FROM [Table]
I am submitting the following query in Sql Server (2008)
WITH query AS (SELECT TOP 100 PERCENT
ROW_NUMBER() OVER
(ORDER BY [tbl2].[col2] ASC) AS TableRowNumber ,
[tbl1].[col1] ,
[tbl2].[col2]
FROM [db1].[dbo].[tbl1] AS [tbl1]
JOIN [db2].[dbo].[tbl2] AS [tbl2]
ON [tbl1].[id] = [tbl2].[id])
SELECT
*
FROM query
WHERE TableRowNumber BETWEEN 1 AND 15
ORDER BY TableRowNumber ASC
When this query is run, it returns the following error message:
Msg 207, Level 16, State 1, Line 3
Invalid column name 'col2'.
The sql join itself runs fine (when run as a normal query. The issue seems to be with using the Row_Number() over (Order By COLUMN) when COLUMN is in a different database from the FROM table of the query.
If I would change line 3 to read (Order By [tbl1].[col1] ASC) then it runs without any issues. The error only happens when the sort column is in a different DB.
Does anyone know why this is happening? Any suggestions on how to fix this?
This works for me no problem:
SELECT a.name, b.object_id, rn = ROW_NUMBER() OVER (ORDER BY b.object_id DESC)
FROM sys.columns AS a
INNER JOIN tempdb.sys.objects AS b
ON a.object_id = b.object_id;
So I suspect there is some other issue going on (e.g. col2 really doesn't exist). Also I noticed that you are calling the thing tb2 and tbl2 - is it possible you have both a tb2 and a tbl2 in the other database, and you're referencing the wrong one?
EDIT I created this:
CREATE DATABASE db1;
GO
USE db1;
GO
CREATE TABLE dbo.tbl1(ID INT, col1 INT);
GO
INSERT dbo.tbl1 SELECT 1, 5
UNION ALL SELECT 2, 10;
GO
CREATE DATABASE db2;
GO
USE db2;
GO
CREATE TABLE dbo.tbl2(ID INT, col2 INT);
GO
INSERT dbo.tbl2 SELECT 1, 9
UNION ALL SELECT 2, 4;
GO
USE db1;
GO
Then ran your query in the context of db1. It ran fine. So for the last time I will suggest that there is something you're not telling us about the schema, or perhaps the fact that you've obfuscated the names (and already had to correct one typo from doing so) has obfuscated something too much even for you...
I have a customer transaction table. I need to create a query that includes a serial number pseudo column. The serial number should be automatically reset and start over from 1 upon change in customer ID.
Now, I am familiar with the row_number() function in SQL. This doesnt exactly solve my problem because to the best of my knowledge the serial number will not be reset in case the order of the rows change.
I want to do this in a single query (SQL Server) and without having to go through any temporary table usage etc. How can this be done?
Sometime we might don't want to apply ordering on our result set to add serial number. But if we are going to use ROW_NUMBER() then we have to have a ORDER BY clause. So, for that we can simply apply a tricks to avoid any ordering on the result set.
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS ItemNo, ItemName FROM ItemMastetr
For that we don't need to apply order by on our result set. We'll just add ItemNo on our given result set.
select
ROW_NUMBER() Over (Order by CustomerID) As [S.N.],
CustomerID ,
CustomerName,
Address,
City,
State,
ZipCode
from Customers;
I'm not certain, based on your question if you want numbered rows that will remember their numbers even if the underlying data changes (and gives a different ordering), but if you just want numbered rows - that reset on a change in customer ID, then try using the Partition by clause of row_number()
row_number() over(partition by CustomerID order by CustomerID)
Implementing Serial Numbers Without Ordering Any of the Columns
Demo SQL Script-
IF OBJECT_ID('Tempdb..#TestTable') IS NOT NULL
DROP TABLE #TestTable;
CREATE TABLE #TestTable (Names VARCHAR(75), Random_No INT);
INSERT INTO #TestTable (Names,Random_No) VALUES
('Animal', 363)
,('Bat', 847)
,('Cat', 655)
,('Duet', 356)
,('Eagle', 136)
,('Frog', 784)
,('Ginger', 690);
SELECT * FROM #TestTable;
There are ‘N’ methods for implementing Serial Numbers in SQL Server. Hereby, We have mentioned the Simple Row_Number Function to generate Serial Numbers.
ROW_NUMBER() Function is one of the Window Functions that numbers all rows sequentially (for example 1, 2, 3, …) It is a temporary value that will be calculated when the query is run. It must have an OVER Clause with ORDER BY. So, we cannot able to omit Order By Clause Simply. But we can use like below-
SQL Script
IF OBJECT_ID('Tempdb..#TestTable') IS NOT NULL
DROP TABLE #TestTable;
CREATE TABLE #TestTable (Names VARCHAR(75), Random_No INT);
INSERT INTO #TestTable (Names,Random_No) VALUES
('Animal', 363)
,('Bat', 847)
,('Cat', 655)
,('Duet', 356)
,('Eagle', 136)
,('Frog', 784)
,('Ginger', 690);
SELECT Names,Random_No,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS SERIAL_NO FROM #TestTable;
In the Above Query, We can Also Use SELECT 1, SELECT ‘ABC’, SELECT ” Instead of SELECT NULL. The result would be Same.
SELECT ROW_NUMBER() OVER (ORDER BY ColumnName1) As SrNo, ColumnName1, ColumnName2 FROM TableName
select ROW_NUMBER() over (order by pk_field ) as srno
from TableName
Using Common Table Expression (CTE)
WITH CTE AS(
SELECT ROW_NUMBER() OVER(ORDER BY CustomerId) AS RowNumber,
Customers.*
FROM Customers
)
SELECT * FROM CTE
I found one solution for MYSQL its easy to add new column for SrNo or kind of tepropery auto increment column by following this query:
SELECT #ab:=#ab+1 as SrNo, tablename.* FROM tablename, (SELECT #ab:= 0)
AS ab
ALTER function dbo.FN_ReturnNumberRows(#Start int, #End int) returns #Numbers table (Number int) as
begin
insert into #Numbers
select n = ROW_NUMBER() OVER (ORDER BY n)+#Start-1 from (
select top (#End-#Start+1) 1 as n from information_schema.columns as A
cross join information_schema.columns as B
cross join information_schema.columns as C
cross join information_schema.columns as D
cross join information_schema.columns as E) X
return
end
GO
select * from dbo.FN_ReturnNumberRows(10,9999)