Semantic Search example from AdventureWorks database of SQL Server - sql

I'm trying to implement semantic search of SQL Server. To see an example, I downloaded AdventureWorks2012 (An 'almost' step by step guide is here: https://learn.microsoft.com/en-us/sql/relational-databases/search/find-similar-and-related-documents-with-semantic-search?view=sql-server-2017). The error says that #CandidateID and #MatchedID have to be declared
I tried to declare those ID, instead of getting the error or a result I get an empty table.
SELECT TOP(10) KEY_TBL.matched_document_key AS Candidate_ID
FROM SEMANTICSIMILARITYTABLE
(
HumanResources.JobCandidate,
Resume,
#CandidateID
) AS KEY_TBL
ORDER BY KEY_TBL.score DESC;
GO
SELECT TOP(5) KEY_TBL.keyphrase, KEY_TBL.score
FROM SEMANTICSIMILARITYDETAILSTABLE
(
HumanResources.JobCandidate,
Resume, #CandidateID,
Resume, #MatchedID
) AS KEY_TBL
ORDER BY KEY_TBL.score DESC;
GO

You need to declare these variables and assign values. Only you know the data type of these keys.For example:
declare #CandidateID int = 6754,
#MatchedID int = 4321
IDs contain real ids from your indexed table.

Related

Implementation of pagination in coldfusion

We are trying to implement pagination in coldfusion.So that I need to make changes in sql query to fetch only a perticular number of data and when clicking on next button, next set of data should be queried.
SELECT History.*,User.FirstName,User.LastName
FROM History
LEFT OUTER JOIN User ON History.UserID = User.UserID
WHERE History.UserID = <CFQUERYPARAM VALUE="#UserID#" CFSQLTYPE="CF_SQL_INTEGER">
AND Type IS NOT NULL
AND SubType IS NOT NULL
ORDER BY #OrderBy# #sort#
Can anyone help me to do the same with above given query.
example query :
SELECT * FROM (
SELECT ROW_NUMBER() OVER(ORDER BY SearchID) AS NUMBER,
* FROM search_history
WHERE UserID=111
AND Date >= #DateVal#
) AS TBL
WHERE NUMBER BETWEEN ((#pageNum# - 1) * #MaxRows# + 1) AND (#pageNum# * #MaxRows#)
ORDER BY #OrderBy# #sort#
First, this is an issue with SQL Server and not ColdFusion. You're just generating the query inline with ColdFusion. It would be better if you create this query as a stored procedure, which by nature would perform better than an inline query.
Second, this answer is the basis for the example I'm posting. SQL Server famously has not supported OFFSET and LIMIT, which makes paging dead simple. These have been in MySQL and postgreSql forever.
Third, as of SQL Server 2012, there is now support for OFFSET and FETCH (essentially LIMIT). Here is a good example of how that works.
This example uses SQL #parameters. Ideally you would declare these in a stored procedure, but you can declare and set them in your inline query. Just make sure to use cfqueryparam to protect against SQL Injection attacks.
SELECT *
FROM (
SELECT
h.column1
, h.column2
, u.FirstName
, u.LastName
, SELECT ROW_NUMBER() OVER ( ORDER BY #ORDER_BY #SORT_ORDER ) AS RowNum
FROM
dbo.History h
INNER JOIN
dbo.User u ON h.UserID = u.UserID
WHERE
h.UserID = #USER_ID
AND
h.Type IS NOT NULL
AND
h.SubType IS NOT NULL
) AS HistorySearch
WHERE
RowNum >= #ROW_START
AND
RowNum < #ROW_END
ORDER BY
RowNum
You'll want to calculate the values of ROW_START and ROW_END based on the page number and a page size variable.
Finally, don't use SELECT * in your main select query. It's a bad practice.
Depending on how much data you are returning you can do your query normally and do pagination on the output with cold fusion. And if you can avoid using * in the query that is a good idea.
<cfparam name="StartAt" default="1">
<cfparam name="MaxRows" default="100">
<cfoutput name="QueryName" startrow="#StartAt#" maxrows="#maxRows#" >
The variables MaxRows and StartAt would be set in your form, and passed when the user clicks Next or previous.
If you have a very large result set then limiting the data returned would be a better idea as you have put forward.

SQL Server : join on uniqueidentifier

I have two tables Backup and Requests.
Below is the script for both the tables
Backup
CREATE TABLE UserBackup(
FileName varchar(70) NOT NULL,
)
File name is represented by a guid. Sometimes there is some additional information related to the file. Hence we have entries like guid_ADD entried in table.
Requests
CREATE TABLE Requests(
RequestId UNIQUEIDENTIFIER NOT NULL,
Status int Not null
)
Here are some sample rows :
UserBackup table:
FileName
15b993cc-e8be-405d-bb9f-0c58b66dcdfe
4cffe724-3f68-4710-b785-30afde5d52f8
4cffe724-3f68-4710-b785-30afde5d52f8_Add
7ad22838-ddee-4043-8d1f-6656d2953545
Requests table:
RequestId Status
15b993cc-e8be-405d-bb9f-0c58b66dcdfe 1
4cffe724-3f68-4710-b785-30afde5d52f8 1
7ad22838-ddee-4043-8d1f-6656d2953545 2
What I need is to return all the rows from userbackup table whose name (the guid) is matches RequestId in the Requests table and the status is 1. So here is the query I wrote
Select *
from UserBackup
inner join Requests on UserBackup.FileName = Requests.RequestId
where Requests.Status = 1
And this works fine. It returns me the following result
FileName RequestId Status
15b993cc-e8be-405d-bb9f-0c58b66dcdfe 15b993cc-e8be-405d-bb9f-0c58b66dcdfe 1
4cffe724-3f68-4710-b785-30afde5d52f8 4cffe724-3f68-4710-b785-30afde5d52f8 1
4cffe724-3f68-4710-b785-30afde5d52f8_Add 4cffe724-3f68-4710-b785-30afde5d52f8 1
This is exactly what I want. But what I don't understand is how it is working. If you notice the result is returning 4cffe724-3f68-4710-b785-30afde5d52f8_Add row as well. The inner join is on varchar and uniqueidentifier, and this join instead of working like "Equals to" comparison works like "contains" comparison. I want to know how this works so that I can be sure to use this code without any unexpected scenarios.
The values on both sides of a comparison have to be of the same data type. There's no such thing as, say, comparing a uniqueidentifier and a varchar.
uniqueidentifier has a higher precedence than varchar so the varchars will be converted to uniqueidentifiers before the comparison occurs.
Unfortunately, you get no error or warning if the string contains more characters than are needed:
select CONVERT(uniqueidentifier,'4cffe724-3f68-4710-b785-30afde5d52f8_Add')
Result:
4CFFE724-3F68-4710-B785-30AFDE5D52F8
If you want to force the comparison to occur between strings, you'll have to perform an explicit conversion:
Select *
from UserBackup
inner join Requests
on UserBackup.FileName = CONVERT(varchar(70),Requests.RequestId)
where Requests.Status = 1
When you compare two columns of different data types SQL Server will attempt to do implicit conversion on lower precedence.
The following comes from MSDN docs on uniqueidentifier
The following example demonstrates the truncation of data when the
value is too long for the data type being converted to. Because the
uniqueidentifier type is limited to 36 characters, the characters that
exceed that length are truncated.
DECLARE #ID nvarchar(max) = N'0E984725-C51C-4BF4-9960-E1C80E27ABA0wrong';
SELECT #ID, CONVERT(uniqueidentifier, #ID) AS TruncatedValue;
http://msdn.microsoft.com/en-us/library/ms187942.aspx
Documentation is clear that data is truncated
When ever you are unsure about your join operation you can verify Actual Execution Plan.
Here is test sample that you can run inside SSMS or SQL Sentry Plan Explorer
DECLARE #userbackup TABLE ( _FILENAME VARCHAR(70) )
INSERT INTO #userbackup
VALUES ( '15b993cc-e8be-405d-bb9f-0c58b66dcdfe' ),
( '4cffe724-3f68-4710-b785-30afde5d52f8' ),
( '4cffe724-3f68-4710-b785-30afde5d52f8_Add' )
, ( '7ad22838-ddee-4043-8d1f-6656d2953545' )
DECLARE #Requests TABLE
(
requestID UNIQUEIDENTIFIER
,_Status INT
)
INSERT INTO #Requests
VALUES ( '15b993cc-e8be-405d-bb9f-0c58b66dcdfe', 1 )
, ( '4cffe724-3f68-4710-b785-30afde5d52f8', 1 )
, ( '7ad22838-ddee-4043-8d1f-6656d2953545', 2 )
SELECT *
FROM #userbackup u
JOIN #Requests r
ON u.[_FILENAME] = r.requestID
WHERE r.[_Status] = 1
Instead of regular join operation SQL Server is doing HASH MATCH with EXPR 1006 in SSMS it is hard to see what is doing but if you open XML file you will find this
<ColumnReference Column="Expr1006" />
<ScalarOperator ScalarString="CONVERT_IMPLICIT(uniqueidentifier,#userbackup.[_FILENAME] as [u].[_FILENAME],0)">
When ever in doubt check execution plan and always make sure to match data types when comparing.
This is great blog Data Mismatch on WHERE Clause might Cause Serious Performance Problems from Microsoft engineer on exact problem.
What is happening here is the FileName is being converted from varchar to a UniqueIdentifier, and during that process it ignores anything after the first 36 characters.
You can see it in action here
Select convert(uniqueidentifier, UserBackup.FileName), FileName
from UserBackup
It works, but to reduce confusion for the next person to come along, you might want to store the RequestId associated with the UserBackup as a GUID in the UserBackup table and join on that.
At the very least put a comment in ;)

SQL conversion from varchar to uniqueidentifier fails in view

I'm stuck on the following scenario.
I have a database with a table with customer data and a table where I put records for monitoring what is happening on our B2B site.
The customer table is as follow:
ID, int, not null
GUID, uniqueidentfier, not null, primary key
Other stuff...
The monitoring table:
ID, int, not null
USERGUID, uniqueidentifier, null
PARAMETER2, varchar(50), null
Other stuff...
In PARAMETER1 are customer guids as wel as other data types stored.
Now the question came to order our customers according their last visit date, the most recent visited customers must come on the top of a grid.
I'm using Entity Framework and I had problems of comparing the string and the guid type, so I decided to make a view on top of my monitoring table:
SELECT
ID,
CONVERT(uniqueidentifier, parameter2) AS customerguid,
USERguid,
CreationDate
FROM
MONITORING
WHERE
(dbo.isuniqueidentifier(parameter2) = 1)
AND
(parameter1 LIKE 'Customers_%' OR parameter1 LIKE 'Customer_%')
I imported the view in EF and made my Linq query. It returned nothing, so I extracted the generated SQL query. When testing the query in SQL Management Studio I got the following error:
Conversion failed when converting from a character string to uniqueidentifier.
The problem lies in the following snippet (simplified for this question, but also gives an error:
SELECT *,
(
SELECT
[v_LastViewDateCustomer].[customerguid] AS [customerguid]
FROM [dbo].[v_LastViewDateCustomer] AS [v_LastViewDateCustomer]
WHERE c.GUID = [v_LastViewDateCustomer].[customerguid]
)
FROM CM_CUSTOMER c
But when I do a join, I get my results:
SELECT *
FROM CM_CUSTOMER c
LEFT JOIN
[v_LastViewDateCustomer] v
on c.GUID = v.customerguid
I tried to make a SQL fiddle, but it is working on that site. http://sqlfiddle.com/#!3/66d68/3
Anyone who can point me in the right direction?
Use
TRY_CONVERT(UNIQUEIDENTIFIER, parameter2) AS customerguid
instead of
CONVERT(UNIQUEIDENTIFIER, parameter2) AS customerguid
Views are inlined into the query and the CONVERT can run before the WHERE.
For some additional discussion see SQL Server should not raise illogical errors

Randomly Select a Row with SQL in Access

I have a small access database with some tables. I am trying the code in the sql design within access. I just want to randomly select a record within a table.
I created a simple table called StateAbbreviation. It has two columns: ID and Abbreviation. ID is just an autonumber and Abbreviation are different abbreviations for states.
I saw this thread here. So I tried
SELECT Abbreviation
FROM STATEABBREVIATION
ORDER BY RAND()
LIMIT 1;
I get the error Syntax error (missing operator) in query expresion RAND() LIMIT 1. So I tired RANDOM() instead of RAND(). Same error.
None of the others worked either. What am I doing wrong? Thanks.
Ypercude provided a link that led me to the right answer below:
SELECT TOP 1 ABBREVIATION
FROM STATEABBREVIATION
ORDER BY RND(ID);
Note that for RND(), I believe that it has to be an integer value/variable.
You need both a variable and a time seed to not get the same sequence(s) each time you open Access and run the query - and to use Access SQL in Access:
SELECT TOP 1 Abbreviation
FROM STATEABBREVIATION
ORDER BY Rnd(-Timer()*[ID]);
where ID is the primary key of the table.
Please try this, it is helpful to you
It is possible by using a stored procedure and function, which I created it's have a extra column which you could be create in your table FLAG name and column all field value should be 0 Then it works
create Procedure proc_randomprimarykeynumber
as
declare #Primarykeyid int
select top 1
#Primarykeyid = u.ID
from
StateAbbreviation u
left join
StateAbbreviation v on u.ID = v.ID + 1
where
v.flag = 1
if(#Primarykeyid is null )
begin
UPDATE StateAbbreviation
SET flag = 0
UPDATE StateAbbreviation
SET flag = 1
WHERE ID IN (SELECT TOP 1 ID
FROM dbo.StateAbbreviation)
END
ELSE
BEGIN
UPDATE StateAbbreviation
SET flag = 0
UPDATE StateAbbreviation
SET flag = 1
WHERE ID IN (#Primarykeyid)
END
SET #Primarykeyid = 1
SELECT TOP 1
ID, Abbreviation
FROM
StateAbbreviation
WHERE
flag = 1
It is made in stored procedure run this and get serial wise primary key
exec proc_randomprimarykeynumber
Thanks and regard
Try this:
SELECT TOP 1 *
FROM tbl_name
ORDER BY NEWID()
Of course this may have performance considerations for large tables.

Why function won't call in SQL Server

I'm trying to create / call a function on the Stack Exchange Data Explorer - I haven't done much SQL Server before but only MySQL.
Why won't it let me call this function I've just made?
-- Get Post with Best Comment on Site
-- Gets the Post with the Best Comment on the Site and Associated Data
CREATE FUNCTION typeOfPost
(#PostId int(11))
RETURNS varchar(30)
AS
BEGIN
declare #PostTypeId int(3)
select #PostTypeId = (SELECT PostTypeId FROM posts WHERE PostId = #PostId)
return (SELECT Name FROM PostTypes WHERE Id = #PostTypeId)
end
SELECT PostId, typeOfPost(PostId) AS [Post Type]
FROM comments
WHERE Score = (
SELECT max(Score)
FROM comments
);​​​​​​​​​​​
It gives:
"SELECT"."typeOfPost" is not a recognized built in function name.
So I looked at examples of function calls in SQL Server and I saw a lot had ".dbo" on the front. If I put that on I get this:
Incorrect syntax near the keyword 'SELECT'.
Can anyone explain what's wrong with my function?
I cleaned up your code so it's valid (no size on ints, correct column name for Posts.Id):
CREATE FUNCTION typeOfPost
(#PostId int)
RETURNS varchar(30)
AS
BEGIN
declare #PostTypeId int
select #PostTypeId = (SELECT PostTypeId FROM posts WHERE Id = #PostId)
return (SELECT Name FROM PostTypes WHERE Id = #PostTypeId)
end
​
And then you get:
Error: CREATE FUNCTION permission denied in database 'StackOverflow.Exported'.\
You can't create objects in StackOverflow Data Explorer. The best object creation you can hope for is table variables.
In addition, the reason you get the error is that when the batch is syntax checked, the function doesn't exist, so the second statement won't work. In traditional SSMS environment, you would create the function in a batch and then execute using the function in another batch. This can be done in a single file using the GO batch separator. This is a feature of SSMS and some other tools (and can be overridden in the options).
In addition, the problem you are trying to solve is not normally one solved with scalar functions (and certainly not ones which individually make trips to tables to retrieve data). Normally you would handle this very simply with a JOIN, which is a lot more accessible to the optimizer than a scalar function, which tend to be treated as block boxes.
Prefix the function with the function's schema name. Probably just dbo., unless you specified something different.
SELECT PostId, dbo.typeOfPost(PostId) AS [Post Type]
FROM comments
WHERE Score = (
SELECT max(Score)
FROM comments
);​​​​​​​​​​​
You can get the same results without the function call like this:
SELECT TOP 1 c.postId,Pt.Name as [Post Type]
FROM comments c
JOIN posts p ON c.PostID=p.postID
JOIN PostTypes Pt on Pt.postTypeID=p.PostTypeId
ORDER BY c.Score DESC
I think your error message is caused by the INT(xx) syntax, which SQL doesn't accept. Also, add the GO keyword between your function definition and your SELECT clause that uses the function...