SQL Query to order by with case - sql

Hi here I'm trying to put order by based on case. Here is my trail and I'm getting syntax error at 'END'
Can someone tell me whats wrong in this?
CREATE TABLE [Emp](
[Id] [nvarchar](50) NULL,
[Name] [varchar](50) NULL
) ON [PRIMARY]
GO
insert into emp values ('01','one')
insert into emp values ('02','Two')
insert into emp values ('3','Three')
insert into emp values ('10','Ten')
insert into emp values ('01A','oneA')
insert into emp values ('*','Star')
go
declare #sortby varchar(100)
set #sortby = 'Id'
select * from emp
ORDER BY
CASE #sortby
WHEN 'Id' THEN
CASE
WHEN ISNUMERIC(Id)=1
THEN CAST(Id as int)
WHEN PATINDEX('%[^0-9]%',Id) > 1
THEN CAST(LEFT(Id,PATINDEX('%[^0-9]%',Id) - 1) as int)
ELSE 2147483648
END
CASE
WHEN ISNUMERIC(Id)=1
THEN NULL
WHEN PATINDEX('%[^0-9]%',Id) > 1
THEN SUBSTRING(Id,PATINDEX('%[^0-9]%',Id) ,50)
ELSE Id
END
END,
Name

Related

Continue insert if one row fails in SQL Server

I have a question about SQL Server - how to continue insert if one row fails?
I have two tables, emp and empref. I want insert rows into the empref table using emp table.
While inserting, one of the rows fails with an "unexpected format" error. emp and empref both have the same columns, but datatypes are different.
Source : emp
CREATE TABLE [dbo].[emp]
(
[id] [varchar](50) NULL,
[name] [varchar](50) NULL,
[sal] [int] NULL
)
INSERT INTO [dbo].[emp] ([id], [name], [sal]) VALUES (N'1', N'abc', 100)
INSERT INTO [dbo].[emp] ([id], [name], [sal]) VALUES (N'2', N'xyz', 200)
INSERT INTO [dbo].[emp] ([id], [name], [sal]) VALUES (N'a4', N'un', 300)
In the empref ref expected int value but one values alphanumeric values.
CREATE TABLE [dbo].[empref]
(
[id] [int] NULL,
[name] [varchar](50) NULL,
[sal] [int] NULL
)
Expected result in empref table :
id |name | name
---+-----+------
1 |abc | 100
2 |xyz | 200
I tried like this:
BEGIN TRY
INSERT INTO empref
SELECT * FROM emp
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() erro
END CATCH
This query is not returning the expected result.
Please tell me how to write the query to achieve this task in SQL Server
You can use TRY_CAST to check if the conversion will work
INSERT INTO empref
(id, name, sal)
SELECT
TRY_CAST(e.id AS int),
e.name,
e.sal
FROM emp e
WHERE TRY_CAST(e.id AS int) IS NOT NULL;
db<>fiddle
Note: Always specify columns to be inserted into.

How to Use Exists in self join

I want those Id whose Orgorder never equal to 1.
CREATE TABLE [dbo].[TEST](
[ORGORDER] [int] NULL,
[Id] [int] NOT NULL,
[ORGTYPE] [varchar](30) NULL,
ORGID INT NULL,
[LEAD] [decimal](19, 2) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE] ,ORGID, [LEAD]) VALUES (1, 100, N'ABC',1, NULL)
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE],ORGID, [LEAD]) VALUES (0, 100, N'ABC',2, 0)
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE],ORGID, [LEAD]) VALUES (0, 100, N'ACD',1, NULL)
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE],ORGID, [LEAD]) VALUES (0, 101, N'ABC',0, 0)
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE],ORGID, [LEAD]) VALUES (2, 101, N'ABC',4, NULL)
GO
I am using exists but getting my result.
Expected result is -
ID
101
You can do this with one pass of the data, and order all ORGORDER = 1 first, then if it's the first row and it has the ORGORDER value you want to exclude, you can just ignore it.
;WITH x AS
(
SELECT Id, rn = ROW_NUMBER() OVER
(PARTITION BY Id ORDER BY CASE WHEN ORGORDER = 1 THEN 1 ELSE 2 END)
FROM dbo.TEST
)
SELECT Id FROM x WHERE rn = 1 AND ORGORDER <> 1;
Example db<>fiddle
Use a subquery in a NOT EXISTS clause, linking the subquery table to the outer query table by ID:
SELECT DISTINCT T1.ID
FROM dbo.TEST AS T1
WHERE NOT EXISTS (
SELECT *
FROM dbo.TEST AS T2
WHERE T1.ID = T2.ID
AND T2.ORGORDER = 1
)
db<>fiddle
An option would be using an aggregation with a suitable HAVING clause such as
SELECT [Id]
FROM [dbo].[TEST]
GROUP BY [Id]
HAVING SUM(CASE WHEN [ORGORDER] = 1 THEN 1 ELSE 0 END) = 0
where if there's at least one value equals to 1 for the concerned column([ORGORDER]), then that [Id] column won't be listed as result.
Demo

How to get rows In each Group with minimum order group and special name in SQL Server

i have a table similar this
CREATE TABLE [dbo].[Test](
[Name] [NCHAR](10) NULL,
[GroupId] [INT] NULL,
[GroupOrder] [INT] NULL
)
and below values
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('A',1,1)
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('A-1',1,2)
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('B',2,1)
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('B',2,2)
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('B-1',2,3)
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('C',3,1)
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('C-1',3,2)
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('C-1',3,3)
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('D',4,1)
INSERT INTO [dbo].[Test]([Name],[GroupId],[GroupOrder]) VALUES ('D',4,2)
i need output like this: rows In each Group with minimum order group and name field contain "-1"
Name GroupId GroupOrder
A-1 1 2
C-1 3 2
B-1 2 3
You could use charindex, top 1 with ties, and row_number
select Top (1) with ties
*
from Test t
where charindex('-1', t.Name ) > 0
order by row_number() over(partition by t.GroupId order by t.GroupOrder)
Demo link: http://rextester.com/RBBKX12749
You can use this
Select * from
(
select *,Row_Number() Over(Partition by GroupId Order by GroupOrder asc) as rn
From yourtable
Where Name like '%-1%'
) a
Where rn = 1
CREATE TABLE [dbo].[#Test](
[Name] [NCHAR](10) NULL,
[GroupId] [INT] NULL,
[GroupOrder] [INT] NULL
)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('A',1,1)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('A-1',1,2)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('B',2,1)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('B',2,2)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('B-1',2,3)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('C',3,1)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('C-1',3,2)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('C-1',3,3)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('D',4,1)
INSERT INTO [dbo].[#Test]([Name],[GroupId],[GroupOrder]) VALUES ('D',4,2)
select * from #Test
Select * from
(
select *,Row_Number() Over(Partition by Name Order by GroupOrder asc) as rn
From #Test
Where Name like '%[-1]%'
) a
Where rn = 1
ORDER BY GroupOrder
OUTPUT
Name GroupId GroupOrder
A-1 1 2
B-1 2 3
C-1 3 2
Use ROW_NUMBER window function
Select * from
(
select *,Row_Number() Over(Partition by Name Order by GroupOrder asc) as rn
From yourtable
Where rtrim(Name) like '[A-Z]-1'
) a
Where rn = 1
If the Name should end with -1 then use Where Name like '%-1'. If Name just contains -1 then Where Name like '%-1%'

sql query to insert values to auto increament column

Hi I want to populate value for Auto increament column when insert value for a table from another table. below is query im using and it throws error
create table test12
(
Id int,
name varchar(255),
dept varchar(255)
)
insert into test12 values(1,'f','cs'),(2,'b','cse'),(3,'c','cs'),(4,'d','cse'),(5,'e','cs'),(6,'f',null)
select * from test12
create table test34
(
seq int identity(1,1) not null,
name varchar(255) not null,
dept varchar(255) default('cs')
)
insert into test34(seq,name,dept) values
(1,(select name from test12),
(select case when dept='cse' then 'Y' else 'N' end as dept from test12))
Please let me what is the mistake
you need not to give values for Identity column, it is auto added, just exclude identity column form insert as:
INSERT INTO test34 (name, dept)
SELECT
name,
CASE WHEN dept = 'cse' THEN 'Y' ELSE 'N' END AS dept
FROM test12
If you really want to add Identity values manually try below SET statements.
SET IDENTITY_INSERT test34 ON;
INSERT INTO test34 (seq, name, dept)
SELECT
ID
name,
CASE WHEN dept = 'cse' THEN 'Y' ELSE 'N' END AS dept
FROM test12
SET IDENTITY_INSERT test34 OFF;
You can turn ON or OFF the IDENTITY_INSERT
SET IDENTITY_INSERT test34 ON
insert into test34(seq,name,dept) values
(1,(select name from test12),
(select case when dept='cse' then 'Y' else 'N' end as dept from test12))
SET IDENTITY_INSERT test34 OFF
There is no need to insert value for auto increment column automatically it will generate values.
insert into test34(name,dept)
select name, Case when dept='cse' then 'Y' else 'N' end as dept from test12

SQL SCOPE_IDENTITY or OUTPUT with data from another table

I'm trying to get the ID of each row inserted from a mass insert and create a mapping table with an ID from my temp table #InsertedClients. I'm using the same temp table for the initial insert but the PDATClientID is not part of the insert. I can't seem to figure out how to do this correctly. When I inserting into the Client_Mapping table using SCOPE_IDENTITY it only grabs the ID from the first insert and puts it along with all of my PDATClientIDs. After doing a lot of Googling I believe I should be using OUTPUT, but can't seem to figure how to put the INSERTED.CLID for each record together with each PDATClientID. I should also say that I can't use a cursor there are too rows. Any help is greatly appreciated!
IF NOT EXISTS (
SELECT ID
FROM sysobjects
WHERE id = object_id(N'[Client_Mapping]')
AND OBJECTPROPERTY(id, N'IsUserTable') = 1
)
CREATE TABLE [Client_Mapping] (
ClientMappingID INT Identity(1, 1) NOT NULL
,PDATClientID INT NOT NULL
,CLID INT NOT NULL
,AUDITDATE DATETIME NOT NULL
,CONSTRAINT [PK_Client_Mapping] PRIMARY KEY (ClientMappingID)
)
-- Begin Inserts
SELECT
First_Name
,Middle_Name
,Last_Name
,CONVERT(DATETIME, Date_Of_Birth) AS DOB
,a.Address_Line as Address1
,a.Address_Line_2 as Address2
,a.Zip_Code as ZipCode -- ??? Do I need to account for zipcode + 4
,REPLACE(REPLACE(REPLACE(cphp.Number_Or_Address, '(', ''), ')', '-'), ' ', '') AS HomePhone
,REPLACE(REPLACE(REPLACE(cpcp.Number_Or_Address, '(', ''), ')', '-'), ' ', '') AS CellPhone
,cpem.Number_Or_Address AS EMAIL
,c.Client_ID as PDATClientID
,c.Action AS [ClientAction]
,ca.Action as [ClientAddressAction]
,a.Action AS [AddressAction]
,cphp.Action AS [HomePhoneAction]
,cpcp.Action AS [CellPhoneAction]
,cpem.Action AS [EmailAction]
INTO #InsertClients
FROM Client c
LEFT JOIN Client_Address ca ON ca.Client_ID = c.Client_ID
LEFT JOIN Address a ON a.Address_ID = ca.Address_ID
LEFT JOIN Client_Phone cphp ON cphp.Client_ID = c.Client_ID
AND cphp.Phone_Email_Type = 'HP'
AND cphp.Start_Date = (
SELECT MAX(Start_Date)
FROM Client_Phone
WHERE Client_ID = c.Client_ID
)
LEFT JOIN Client_Phone cpcp ON cpcp.Client_ID = c.Client_ID
AND cpcp.Phone_Email_Type = 'CP'
AND cpcp.Start_Date = (
SELECT MAX(Start_Date)
FROM Client_Phone
WHERE Client_ID = c.Client_ID
)
LEFT JOIN Client_Phone cpem ON cpem.Client_ID = c.Client_ID
AND cpem.Phone_Email_Type = 'EM'
AND cpem.Start_Date = (
SELECT MAX(Start_Date)
FROM Client_Phone
WHERE Client_ID = c.Client_ID
)
where c.action ='I'
BEGIN TRY
BEGIN TRAN
INSERT INTO [dbo].[Clients] (
[FName]
,[MiddleInitial]
,[LName]
,[DOB]
,[Address1]
,[Address2]
,[ZipCode]
,[HomePhone]
,[CellPhone]
,[Email]
,[AuditStaffID]
,[AuditDate]
,[DateCreated]
)
Select
First_Name
,CASE when Middle_Name = '' THEN NULL ELSE Middle_Name END
,Last_Name
,DOB
,Address1
,Address2
,ZipCode
,HomePhone
,CellPhone
,EMail
,496 AS [AuditStaffID]
,CURRENT_TIMESTAMP AS [AuditDate]
,CURRENT_TIMESTAMP AS [DateCreated]
FROM
#InsertClients
Where
[ClientAction] = 'I'
INSERT INTO [Client_Mapping]
(
PDATClientID
,CLID
,AUDITDATE
)
SELECT
PDATClientID
,SCOPE_IDENTITY()
,CURRENT_TIMESTAMP
FROM #InsertClients
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
SELECT ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage
END CATCH
you have a hell of a code in your question I can explain you in few line how you can retrieve all the inserted ids.
Yes SCOPE_IDENTITY() gives you the last IDENTITY value generated by the identity column. In you case you will need to use a table variable to get all the generated Identity values during your insert
/* Declare a table Vairable */
DECLARE #NewValues TABLE (IDs INT);
/* In Your Insert Statement use OUTPUT clause */
INSERT INTO Table_Name (Column1,Column2,Column3,....)
OUTPUT inserted.Identity_Column INTO #NewValues (IDs)
SELECT Column1,Column2,Column3,....
FROM Table_Name2
/* Finally Select values from your table variable */
SELECT * FROM #NewValues
Your Query
In your case your insert statement should look something like ...
INSERT INTO [dbo].[Clients] (
[FName]
,[MiddleInitial]
,[LName]
,[DOB]
,[Address1]
,[Address2]
,[ZipCode]
,[HomePhone]
,[CellPhone]
,[Email]
,[AuditStaffID]
,[AuditDate]
,[DateCreated]
)
OUTPUT inserted.[FName], inserted.[MiddleInitial] ,.... INTO #TableVarible(First_Name,[MiddleInitial].....)
Select
First_Name
,CASE when Middle_Name = '' THEN NULL ELSE Middle_Name END
,Last_Name
,DOB
,Address1
,Address2
,ZipCode
,HomePhone
,CellPhone
,EMail
,496 AS [AuditStaffID]
,CURRENT_TIMESTAMP AS [AuditDate]
,CURRENT_TIMESTAMP AS [DateCreated]
FROM
#InsertClients
Where
[ClientAction] = 'I'
Solved the problem by using this example found here: http://sqlserverplanet.com/tsql/match-identity-columns-after-insert. The example from that site is below.
-- Drop temp tables if they already exist
IF OBJECT_ID('TempDB..#source', 'U') IS NOT NULL DROP TABLE #source;
IF OBJECT_ID('TempDB..#target', 'U') IS NOT NULL DROP TABLE #target;
IF OBJECT_ID('TempDB..#xref', 'U') IS NOT NULL DROP TABLE #xref;
GO
-- Create the temp tables
CREATE TABLE #source (id INT PRIMARY KEY IDENTITY(1, 1), DATA INT);
CREATE TABLE #target (id INT PRIMARY KEY IDENTITY(1, 1), DATA INT);
CREATE TABLE #xref (ROW INT PRIMARY KEY IDENTITY(1, 1), source_id INT, target_id INT);
GO
-- If xref table is being reused, make sure to clear data and reseed by truncating.
TRUNCATE TABLE #xref;
-- Fill source table with dummy data (even numbers)
INSERT INTO #source (DATA)
SELECT 2 UNION SELECT 4 UNION SELECT 6 UNION SELECT 8;
GO
-- Fill target table with dummy data (odd numbers) to simulate existing records
INSERT INTO #target (DATA)
SELECT 1 UNION SELECT 3 UNION SELECT 5;
GO
-- Insert source table data into target table. IMPORTANT: Inserted data must be sorted by the source table's primary key.
INSERT INTO #target (DATA)
OUTPUT INSERTED.id INTO #xref (target_id)
SELECT DATA
FROM #source
ORDER BY id ASC;
GO
-- Update the xref table with the PK of the source table. This technique is used for data not captured during the insert.
;WITH src AS (SELECT id, ROW = ROW_NUMBER() OVER (ORDER BY id ASC) FROM #source)
UPDATE x
SET x.source_id = src.id
FROM #xref AS x
JOIN src ON src.ROW = x.ROW;
GO
-- Verify data
SELECT * FROM #source;
SELECT * FROM #target;
SELECT * FROM #xref;
GO
-- Clean-up
IF OBJECT_ID('TempDB..#source', 'U') IS NOT NULL DROP TABLE #source;
IF OBJECT_ID('TempDB..#target', 'U') IS NOT NULL DROP TABLE #target;
IF OBJECT_ID('TempDB..#xref', 'U') IS NOT NULL DROP TABLE #xref;
GO