How to get Order Numbers(189,190) from following TrigParams field in SQL server 2014 Database.
TrigParams
{"OWLSObjKey":{"key":"OWLSObjKey","value":"189","type":null},"OWLSObjType":{"key":"OWLSObjType","value":"17","type":null},"ObjKey":{"key":"ObjKey","value":"189","type":null},"ObjType":{"key":"ObjType","value":"17","type":null}}
{"OWLSObjKey":{"key":"OWLSObjKey","value":"190","type":null},"OWLSObjType":{"key":"OWLSObjType","value":"17","type":null},"ObjKey":{"key":"ObjKey","value":"190","type":null},"ObjType":{"key":"ObjType","value":"17","type":null}}
You see from the other answers, that SQL-Server 2016+ with broad JSON support would be of great help. But without you are not lost. You can use string methods:
credits to Panagiotis Kanavos for the MCVE
declare #table table (trigparams nvarchar(2000))
insert into #table
values
('{"OWLSObjKey":{"key":"OWLSObjKey","value":"189","type":null},"OWLSObjType":{"key":"OWLSObjType","value":"17","type":null},"ObjKey":{"key":"ObjKey","value":"189","type":null},"ObjType":{"key":"ObjType","value":"17","type":null}}'),
('{"OWLSObjKey":{"key":"OWLSObjKey","value":"190","type":null},"OWLSObjType":{"key":"OWLSObjType","value":"17","type":null},"ObjKey":{"key":"ObjKey","value":"190","type":null},"ObjType":{"key":"ObjType","value":"17","type":null}}')
--This is the query
select LEFT(CutOff,CHARINDEX('"',CutOff)-1)
from #table t
CROSS APPLY(SELECT STUFF(t.trigparams,1,CHARINDEX('"value":"',t.trigparams)+8,'')) A(CutOff);
The idea in short:
Within the APPLY we will use STUFF() to write nothing over the first characters up to the number you are looking for (after the first occurance of "value":". This is returned as Column CutOff. We can now use LEFT() to pick the number only.
The question doesn't specify the server version, the table schema or whether the string represents a single value or the contents of two separate rows.
I'll just assume it's SQL Server 2016 which supports JSON and the text comes from two separate rows. I'll also assume the query only needs to return the data as single value.
In this case a simple call to JSON_VALUE('$.OWLSObjKey.value') will return the data. JSON_VALUE returns a single value from a well-formed JSON string :
declare #table table (trigparams nvarchar(2000))
insert into #table
values
('{"OWLSObjKey":{"key":"OWLSObjKey","value":"189","type":null},"OWLSObjType":{"key":"OWLSObjType","value":"17","type":null},"ObjKey":{"key":"ObjKey","value":"189","type":null},"ObjType":{"key":"ObjType","value":"17","type":null}}'),
('{"OWLSObjKey":{"key":"OWLSObjKey","value":"190","type":null},"OWLSObjType":{"key":"OWLSObjType","value":"17","type":null},"ObjKey":{"key":"ObjKey","value":"190","type":null},"ObjType":{"key":"ObjType","value":"17","type":null}}')
select JSON_VALUE(trigparams,'$.OWLSObjKey.value') As SomeKey
from #table
This returns :
SomeKey
189
190
Assuming you're using SQL Server 2016+, use OPENJSON:
SELECT O.OrderNumber
FROM (VALUES('{"OWLSObjKey":{"key":"OWLSObjKey","value":"189","type":null},"OWLSObjType":{"key":"OWLSObjType","value":"17","type":null},"ObjKey":{"key":"ObjKey","value":"189","type":null},"ObjType":{"key":"ObjType","value":"17","type":null}}'),
('{"OWLSObjKey":{"key":"OWLSObjKey","value":"190","type":null},"OWLSObjType":{"key":"OWLSObjType","value":"17","type":null},"ObjKey":{"key":"ObjKey","value":"190","type":null},"ObjType":{"key":"ObjType","value":"17","type":null}}')) V(TrigParams)
CROSS APPLY OPENJSON(V.TrigParams) WITH (OWLSObjKey nvarchar(MAX) AS JSON) OK
CROSS APPLY OPENJSON(OK.OWLSObjKey) WITH (OrderNumber int '$.value') O;
If not, then SQL Server is not your friend for this without using a CLR Function. If you can't use CLR, then I would suggest using a different tool to read the JSON value.
I'm migrating from SybaseIQ to SQL Server 2008, one major diffrence observer is in ORDER BY clause.
Created on table as create table test(name varchar(20))
Inserted some records:
insert into test values('Hi')
insert into test values('Toi')
insert into test values('>Toi')
insert into test values('iHh')
insert into test values('hi')
insert into test values('IhH')
insert into test values('1Hi')
insert into test values('2Hi')
Performed select operation on both SQL Server and Sybase as:
select * from test order by name desc
Result for Sybase is:
name
-------
iHh
hi
Toi
IhH
Hi
>Toi
2Hi
1Hi
And result for SQL server is:
name
-------
Toi
IhH
iHh
Hi
hi
2Hi
1Hi
>Toi
Why this order differ in SQL server and Sybase? How to manage order by in SQL server as compare to Sybase to get same result?
You can use the collation Latin1_General_BIN2 as the SQL server default collation or use the specify collation for the ORDER clause.
Binary collations
Binary collations sort data based on the sequence of
coded values that are defined by the locale and data type. They are
case sensitive. A binary collation in SQL Server defines the locale
and the ANSI code page that will be used. This enforces a binary sort
order. Because they are relatively simple, binary collations help
improve application performance. For non-Unicode data types, data
comparisons are based on the code points that are defined in the ANSI
code page. For Unicode data types, data comparisons are based on the
Unicode code points. For binary collations on Unicode data types, the
locale is not considered in data sorts. For example,
Latin_1_General_BIN and Japanese_BIN yield identical sorting results
when they are used on Unicode data.
There are two types of binary
collations in SQL Server; the older BIN collations and the newer BIN2
collations. In a BIN2 collation all characters are sorted according to
their code points. In a BIN collation only the first character is
sorted according to the code point, and remaining characters are
sorted according to their byte values. (Because the Intel platform is
a little endian architecture, Unicode code characters are always
stored byte-swapped.)
declare #Test table (name varchar(20) collate Latin1_General_BIN2)
insert #Test values ('Hi'), ('Toi'), ('>Toi'), ('iHh'), ('hi'), ('IhH'), ('1Hi'), ('2Hi')
select * from #Test order by name desc
Or just
select * from #Test order by name collate Latin1_General_BIN2 desc
Use ASCII Value for column and order by it in Descending order. ASCII will order your first later of word then you can apply order on your column
SELECT Name FROM #tblTest ORDER BY ASCII(Name) desc,Name
Output in Descending:
Output in Ascending:
I'm looking for an efficient way of how to convert rows to columns in SQL Server. I tried in Toad for Oracle, but now I want it in SQL Server.
This is my example:
CID SENTENCE
1 Hello; Hi;
2 Why; What;
The result should be like
CID SENTENCE
1 Hello
1 Hi
2 Why
2 What
Would you please help me with it?
I would advise you to rethink your database design. It's almost never a good idea to store data in a delimited string in any relational database.
If it's impossible to change your database design, you need to use some UDF to split strings.
There are many different approaches to split strings in sql server, read this article on the differences between the common ways.
You can probably change your chosen split string function to take the cid as well as the sentence as a variable and have it return the data exactly as your desired output for each row in your table.
Then all you have to do is a select from your table with an inner join with the udf on the cid.
try
declare #var table (CID int, SENTENCE varchar(50))
insert into #var(CID,SENTENCE) values
(1,'Hello; Hi;'),
(2,'Why; What;')
select cid,t.c.value('.','varchar(50)') as val
from (select cid,x=cast('<t>'+ replace(stuff(sentence,len(sentence),1,''),';','</t><t>')+'</t>' as xml)
from #var) a cross apply x.nodes('/t') t(c)
I have table categories (c) and an another table (x) with a column which can contain cat IDs separated with comma as varchar data type. I want to Select related categories but I'm having error "Conversion failed when converting the varchar value '5,' to data type int." when trying to select:
SELECT ID, Title FROM c WHERE ID IN (SELECT catIDs FROM x WHERE ID=any);
The subquery returns data like "1,3,4"
You need to split the 1,3,4 string returned by the subquery into separate int values. SQL Server does not have a built-in function to do it, but you can use this user-defined function.
Create the function dbo.Split in your database and then re-write your query as follows:
SELECT ID, Title
FROM c
WHERE ID IN
(
SELECT s
FROM dbo.Split(',', '1,3,4')
)
I replaced the subquery with example results 1,3,4 to shorten the query and make it easier to understand.
If I get it right, you actually have values like "1,3,4" in your column catIDs. So you should extract a substring in the select of your subquery.
By the way, I'm not an MS SQL Server expert, but it's probably a bad database design to do so. I'm not sure the RDBMS engine will use indexes in such a case...
I am using sql server 2008 and I'm trying to build a query for displaying some overall results from a single sql table.
I want to display count(fieldname) for each date, for example I want to know how often the name "izla" is repeated in the table for each date but it could be also "IZLA" or "Izla", so i must find a way to group this data together as one and find count for the three of them.
The problem is that if i try using uppercase or lowercase so that they are considered automatically the same I have the problem: when izla is converted to upper it becomes İZLA or on the other hand when IZLA is converted to lowercase it is displayed ızla.
The big question is how can i group this data together? Maybe the problem comes from using nvarchar but i need the column type to be like that (can't change it).
When you group, you should use an Accent Insensitive collation. You can add this directly to your group by clause. The following is an example:
Declare #Temp Table(Data nvarchar(100))
Insert Into #Temp Values(N'izla')
Insert Into #Temp Values(N'İZLA')
Insert Into #Temp Values(N'IZLA')
Insert Into #Temp Values(N'Izla')
Select Data,
Count(*)
From #Temp
Group By Data
Select Data Collate Latin1_General_CI_AI,
Count(*)
From #Temp
Group By Data Collate Latin1_General_CI_AI
When you run this example, you will see that the first query creates two rows (with count 3 and count 1). The second example uses an accent insensitve collation for the grouping, so all 4 items are grouped together.
I used Latin1_General_CI_AI in my example. I suggest you examine the collation of the column you are using and then use a collation that most closely matches by changing the AS on the end to AI.
Try replacing ı and such with english equivalent after lowercasing
This all comes down to collation, which is the way that the system sorts string data.
You could say something like:
SELECT *, COUNT(*) OVER (PARTITION BY fieldname COLLATE Latin1_General_CI_AI), COUNT(*) OVER (PARTITION BY fieldname COLLATE Latin1_General_CI_AS)
FROM yourtable
This will provide some nice figures for you around how many times each name appeared in the various formats. There are many collations, and you can search in Books Online for a complete list. You may also be interested in Latin1_General_BIN for example.
Rob