write a Query Unique ids with different city's - database

In A Table Cityid and CITYname 2 Columns:
city id city name
1 Bang
1 hyd
1 pune
2 hyd
2 pune
2 chennai
I want the Result:
1 ---hyd,pune,bang(all citynames of city id)
2---

You left off some key details required to answer your question: What language are you using?
Here is the answer if you are using T-SQL on SQL Server 2005/2008:
Your Table:
CREATE TABLE [dbo].[cities](
[cityid] [int] NULL,
[cityname] [varchar](50) NULL
) ON [PRIMARY]
Your Data:
insert into cities(cityid,cityname)values(1,'Seattle')
insert into cities(cityid,cityname)values(1,'Portland')
insert into cities(cityid,cityname)values(2,'New York')
insert into cities(cityid,cityname)values(2,'Newark')
Your Query:
declare #result table(
cityid int,
cityname varchar(max)
)
declare #queue table(
cityid int,
cityname varchar(50)
)
declare #cityid int
declare #cityname varchar(50)
insert into #queue select * from cities
while(exists(select top 1 cityid from #queue)) begin
select top 1 #cityid = cityid, #cityname = cityname from #queue
if(exists(select cityid from #result where cityid = #cityid)) begin
update #result
set cityname = cityname + ', ' + #cityname
where cityid = #cityid
end else begin
insert into #result(cityid,cityname) values(#cityid,#cityname)
end
delete from #queue where cityid = #cityid and cityname = #cityname
end
select * from #result
Your Result:
cityid cityname
1 1 Seattle, Portland
2 2 New York, Newark

look up GROUP_CONCAT
or USER DEFINED AGGREGATE FUNCTIONS

Related

Procedure data input a temp table

I have a procedure which returns the result correctly, but I could not store the procedure result in a single table or temptable.
My procedure return values like this
ItemName
BATH RUG-VDW.WO COTTON CLASSIC FRAME
-------------------------------------------
ItemName ItemCode StyleNo UPC EAN UnitFactor
BATH RUG-VDW.WO COTTON CLASSIC FRAME 4 884631844635 0884631844635 4.580
BATHRUG-VDW.WO COTTON CLASSIC FRAME 5 884631844659 0884631844659 4.580
BATH RUG-VDW.W COTTON CLASSIC FRAME 6 884631844666 0884631844666 4.580
ItemName
BATH RUG-VDW.WOVEN COTTON CLASSIC FRAME 12-840
-------------------------------------------
ItemName ItemCode StyleNo UPC EAN UnitFactor
BATH RUG-VDW.WOVEN COTTON CLASSIC FRAME 12-840 30 12-840 884631881906 0884631881906 4.580
BATH RUG-VDW.WOVEN COTTON CLASSIC FRAME 12-840 31 12-840 884631881913 0884631881913 4.580
----------------------------------------------------------------------------
Code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_GetDetail]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #tab TABLE (no INT, name VARCHAR(30))
DECLARE #MyCursor CURSOR;
DECLARE #MyField VARCHAR(MAX);
DECLARE #Qry VARCHAR(MAX);
SET NOCOUNT ON;
SET #MyCursor = CURSOR FOR
SELECT DISTINCT ItemName FROM dbo.NewTest
SET #Qry=''
OPEN #MyCursor
FETCH NEXT FROM #MyCursor INTO #MyField
WHILE ##FETCH_STATUS = 0
BEGIN
/* YOUR ALGORITHM GOES HERE */
SET #Qry = #Qry + '; SELECT '''+#MyField+''' AS ItemName'
SET #Qry = #Qry + '; SELECT ItemName, ItemCode, StyleNo, UPC, EAN, UnitFactor FROM NewTest WHERE ItemName = '''+#MyField+''''
FETCH NEXT FROM #MyCursor INTO #MyField
END;
EXEC (#Qry);
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
Cursors should be avoided as much as possible. This returns a single result set. Hope this is OK for your needs.
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
DROP TABLE #MyTempTable;
CREATE TABLE #MyTempTable
(
ItemName NVARCHAR(100) ,
ItemCode NVARCHAR(100) ,
StyleNo NVARCHAR(100) ,
UPC NVARCHAR(100) ,
EAN NVARCHAR(100) ,
UnitFactor NVARCHAR(100) ,
ItemNameGroup NVARCHAR(100)
);
WITH cte
AS ( SELECT [ItemName] ,
[ItemCode] ,
[StyleNo] ,
[UPC] ,
[EAN] ,
[UnitFactor] ,
ROW_NUMBER() OVER ( PARTITION BY [ItemName] ORDER BY [ItemName] ) AS rn
FROM [dbo].[NewTest]
)
INSERT INTO [#MyTempTable]
( [ItemName] ,
[ItemCode] ,
[StyleNo] ,
[UPC] ,
[EAN] ,
[UnitFactor] ,
[ItemNameGroup]
)
SELECT c.[ItemName] ,
c.[ItemCode] ,
c.[StyleNo] ,
c.[UPC] ,
c.[EAN] ,
c.[UnitFactor] ,
t.[ItemName]
FROM [cte] AS c
INNER JOIN ( SELECT [cte].[ItemName]
FROM [cte]
WHERE [cte].[rn] = 1
) t ON c.[ItemName] = t.[ItemName];
SELECT [mtt].[ItemName] ,
[mtt].[ItemCode] ,
[mtt].[StyleNo] ,
[mtt].[UPC] ,
[mtt].[EAN] ,
[mtt].[UnitFactor] ,
[mtt].[ItemNameGroup]
FROM [#MyTempTable] AS [mtt];
If you want the dynamic sql to save values into a temp table, create the temp table first (before the cursor),
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL DROP TABLE #MyTempTable
create table #MyTempTable (ItemName varchar(100), ItemCode varchar(100), StyleNo varchar(100), UPC varchar(100), EAN varchar(100),
UnitFactor varchar(100)) -- change these definitions to match your actual data
then change the code which builds the sql:
Set #Qry=#Qry+'; select '''+#MyField+''' as ItemName'
Set #Qry=#Qry+'; insert into #MyTempTable select ItemName, ItemCode, StyleNo, UPC, EAN,
UnitFactor from NewTest where ItemName ='''+#MyField+''''
the temp table #MyTempTable will be available outside the cursor:
select * from #MyTempTable
drop table #MyTempTable
You return 2 tables, and they have a different structure. You can't store that in a temp table.
Why do you do that first SELECT of just the name anyway? It seems completely redundant.

How to write this procedure to get auto-increment alphanumeric id in SQL Server?

Table structure is as follows:
CREATE TABLE tblContact
(
SrNo DECIMAL IDENTITY(1,1) NOT NULL,
InquiryId VARCHAR(10) PRIMARY KEY,
SenderName VARCHAR(50),
SenderEmail VARCHAR(200),
SenderSubject VARCHAR(50),
SenderMessage VARCHAR(MAX),
IsActive BIT DEFAULT(1),
IsDelete BIT DEFAULT(0),
CreatedOn DATETIME DEFAULT(GETDATE()),
CreatedBy VARCHAR(10),
UpdatedOn DATETIME,
UpdatedBy VARCHAR(10)
)
Procedure listing is as follows:
CREATE PROC Usp_GetNewInquiryId
AS
BEGIN
IF NOT EXISTS(SELECT InquiryId FROM JobPortal.dbo.tblContact)
DECLARE #PrefixValue VARCHAR(10) = 'INQ'
DECLARE #InitialValue DECIMAL(10) = 1001
SELECT InquiryId = #PrefixValue + CAST(ISNULL(MAX(InquiryId), #InitialValue) AS VARCHAR(10))
FROM JobPortal.dbo.tblContact
ELSE
/* here I want to eliminate the word 'INQ' from 'INQ1001' towards left side and do increment 1002 from 1001, lastly want to select INQ1002 and so on... */
SELECT TOP 1
InquiryId = #PrefixValue + CONVERT(VARCHAR(10), SUBSTRING(InquiryId, 4, 4)) + 1
FROM JobPortal.dbo.tblContact
ORDER BY InquiryId DESC
END
Desired Output:
If table is empty then InquiryId=INQ1001
Otherwise InquiryId=INQ1002
If you want to return the "next available" InquiryId for tblContact, I would do this:
CREATE PROCEDURE Usp_GetNewInquiryId
AS
BEGIN
IF NOT EXISTS (SELECT InquiryId FROM tblContact)
SELECT 'INQ1001'
ELSE
SELECT TOP 1 'INQ' + CONVERT(VARCHAR,CONVERT(INT,REPLACE(InquiryId,'INQ','')) + 1) FROM tblContact ORDER BY InquiryId DESC
END

Update table using stored procedure in SQL Server 2014

I have two tables, please see attached schema, and I have written a stored procedure which is not working. Please help me.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[countries]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[Prefix] [nvarchar](max) NULL,
[MinDigits] [int] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[customers]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[Business] [nvarchar](max) NULL,
[Phone] [nvarchar](max) NULL,
[CountryID] [int] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Sample data in the tables:
Id Name Business Phone CountryID
---------------------------------------------------
1 John B&B LLC 001820199202 ***
2 Mike ABC Inc 006192479121 ***
3 Jennifer Coca Cola 0017421 ***
4 Sabine ABC Inc 0091827411 ***
...
Countries:
Id Name Prefix MinDigits
--------------------------------------
1 USA 001 10
2 Australia 0061 11
3 India 0091 9
...
I want to update the CountryID in the customers table based on the countries table.
Result based on above:
Id Name Business Phone CountryID
---------------------------------------------------
1 John B&B LLC 001820199202 1
2 Mike ABC Inc 006192479121 2
3 Jennifer Coca Cola 0017421 ***
4 Sabine ABC Inc 0091827411 3
...
The entry for Jennifer is not updated, since minimum digits are not matching
This is my stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[UpdateCustomer]
AS
BEGIN
SELECT *
INTO #CustomerTable
FROM dbo.customers
DECLARE #Phone NVARCHAR
DECLARE #CountryID INT
DECLARE #Count INT
DECLARE #CustomerID INT
WHILE EXISTS (SELECT * FROM #CustomerTable)
BEGIN
SELECT TOP 1
#Phone = Phone, #CustomerID = Id
FROM
#CustomerTable
IF((SELECT TOP 1 COUNT(*)
FROM countries
WHERE #Phone LIKE Prefix+'%' And LEN(#Phone) <= MinDigits) > 0)
BEGIN
SELECT TOP 1
#CountryID = Id
FROM
countries
WHERE
#Phone LIKE Prefix + '%'
AND LEN(#Phone) <= MinDigits
UPDATE customers
SET CountryID = #CountryID
WHERE Id = #CustomerID
END
DELETE #CustomerTable
WHERE Id = #CustomerID
END
DROP TABLE #CustomerTable
END
You could just do something like this as your entire stored procedure
UPDATE cu
SET cu.CountryId = co.Id
FROM customers cu
JOIN countries co ON cu.phone LIKE co.prefix + '%'
WHERE LEN(cu.phone) >= co.MinDigits
Still, If you want to do it from your SP then define size of #phone variable as
DECLARE #Phone NVARCHAR(30) -- as needed
Its not holding assigned phone number so the update statement is not working.
First of all SQL is set based, so using loop concept is not best idea.
You could use MERGE statement:
MERGE customers c
USING countries cs
ON c.Phone LIKE CONCAT(cs.Prefix, '%')
AND LEN(c.Phone) >= cs.MinDigits
WHEN MATCHED THEN
UPDATE
SET CountryId = cs.Id;
LiveDemo
Use UPDATE FROM
UPDATE customers
SET CountryID = C.Id
FROM
Countries C
WHERE
LEFT(customers.Phone, LEN(C.Prefix)) = C.Prefix AND
LEN(customers.phone) >= C.MinDigits
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[UpdateCustomer]
AS
BEGIN
SELECT *
INTO #CustomerTable
FROM dbo.customers
DECLARE #Phone NVARCHAR(MAX)
DECLARE #CountryID INT
DECLARE #Count INT
DECLARE #CustomerID INT
WHILE EXISTS (SELECT * FROM #CustomerTable)
BEGIN
SELECT TOP 1
#Phone = Phone, #CustomerID = Id
FROM
#CustomerTable
IF((SELECT TOP 1 COUNT(*)
FROM countries
WHERE #Phone LIKE Prefix+'%' And LEN(#Phone) >= MinDigits) > 0)
BEGIN
SELECT TOP 1
#CountryID = Id
FROM
countries
WHERE
#Phone LIKE Prefix + '%'
AND LEN(#Phone) >= MinDigits
UPDATE customers
SET CountryID = #CountryID
WHERE Id = #CustomerID
END
DELETE #CustomerTable
WHERE Id = #CustomerID
END
DROP TABLE #CustomerTable
END

Executing a stored procedure to populate a table column?

Can I use the EXEC keyword to run a stored procedure to populate the QuestionScore column?
CREATE TABLE Question_Result
(
ResultID INT IDENTITY (10000, 1) NOT NULL,
QResultID VARCHAR (10) NOT NULL DEFAULT 'QRES' + CAST(NEXT VALUE
FOR non_identity_incrementer AS VARCHAR(10)),
QuestionScore DECIMAL (4,2) EXEC dbo.update_question_result_question_score(),
Assessment INT NULL,
DateTimeModified DATETIME NOT NULL DEFAULT SYSDATETIME(),
PRIMARY KEY CLUSTERED (ResultID),
FOREIGN KEY (Assessment) REFERENCES Assessment_Result (ResultID)
);
My stored procedure is:
CREATE PROCEDURE update_question_result_question_score (
#QuestionScore DECIMAL(4,2) OUTPUT,
#StudentAnswer NVARCHAR(MAX) OUTPUT,
#AssessingAnswer NVARCHAR(MAX) OUTPUT
)
AS
BEGIN
SELECT *
FROM StudentAnswerQuestionScore
SET #QuestionScore = (SELECT Score FROM StudentAnswerQuestionScore)
SET #StudentAnswer = (SELECT [Student Answer] FROM StudentAnswerQuestionScore)
SET #AssessingAnswer = (SELECT [Assessing Answer] FROM StudentAnswerQuestionScore)
IF (#StudentAnswer = #AssessingAnswer)
INSERT INTO Question_Result (QuestionScore)
VALUES (#QuestionScore)
END
You can try to use function for your computed column. Hopefully below codes can give you some ideas:
use staging
go
create table Question
(
QuestionKey int identity(1,1),
QuestionDesc varchar(50),
AssignedAnswer varchar(50),
Score int
)
go
insert into Question
select 'Capital city of AU', 'ACT', 10
go
create function ufnAssignScore (#Question varchar(50), #Answer varchar(50))
Returns int
as
BEGIN
declare #return int
select #return = Score
FROM Question
where QuestionDesc = #Question and AssignedAnswer = #Answer
return #return
END
go
create table Answer
(
AnswerKey int identity(1,1),
StudentID varchar(50),
QuestionDesc varchar(50),
AnswerDesc varchar(50),
Score as dbo.ufnAssignScore(QuestionDesc, AnswerDesc)
)
go
insert into Answer (StudentID, QuestionDesc, AnswerDesc)
select 'a1', 'Capital city of AU', 'Mel'
union all
select 'a2', 'Capital city of AU', 'ACT'
go
select * from Answer

How to DISPLAY horizontal data into vertical columns in SQL?

I have tables Employees, Documents, Transactions, from_to table.
Employee can send a document to other employee and send a copy of the document to other employee.
data will be displayed in transaction table as follow:
TransId - Document Id - EmployeeId - from_toId
1 1 5 1 (From)
2 1 6 2 (To)
3 1 10 2 (CC)
Now; I want the data above to be displayed as follow:
DocId From To CC
1 Jo(5) Fo(6) Do(10)
I know that we need something to do with "Pivot Table". BUT I DON'T KNOW HOW.
Waiting for your feedback.
I have a solution with a Cursor which is dynamic:
CREATE TABLE #PRERESULT(
[TransId] int,
DocumentID int ,
EmployeeId int ,
from_toId [nvarchar](10)
)
INSERT INTO #PRERESULT ([TransId],DocumentID,EmployeeId,from_toId)
VALUES
(1,1,5,'1 (From)'),
(2,1,6,'2 (To)'),
(3,1,10,'2 (CC)')
CREATE TABLE #RESULT (
DocID int,
[From] nvarchar(15),
[To] nvarchar(15),
CC nvarchar(15))
INSERT INTO #RESULT (DocID)
SELECT DocumentID
FROM #PRERESULT
GROUP BY DocumentID
DECLARE #Documentid int,#Employee int, #Alias nvarchar(10),#SQL nvarchar(250)
DECLARE C_FromTo CURSOR
FOR
SELECT DocumentID,EmployeeID
FROM #PRERESULT
OPEN C_FromTo
FETCH NEXT FROM C_FromTo INTO #Documentid, #Employee
While (##Fetch_status = 0)
BEGIN
SET #Alias = (SELECT SUBSTRING(from_toId,PATINDEX('%(%',from_toId)+1,(LEN(from_toId)-PATINDEX('%(%',from_toId)-1)) FROM #PRERESULT WHERE #Employee = EmployeeId)
SET #SQL = 'UPDATE #RESULT
SET ['+#Alias+'] = '+Convert(nvarchar(50),#Employee)+'
WHERE '+Convert(nvarchar(50),#Documentid)+' = DocID'
EXEC (#SQL)
FETCH NEXT FROM C_FromTo INTO #Documentid, #Employee
END
CLOSE C_FromTo
DEALLOCATE C_FromTO
SELECT * FROM #RESULT
DROP TABLE #PRERESULT
DROP TABLE #RESULT
Gives you this:
DocID |From |To |CC
1 |5 |6 |10
Hope this will help you
Have a nice day & Greets from Switzerland
Etienne
I think this reflects your table, although I am using names instead of IDs for the last two columns:
CREATE TABLE [dbo].[Transaction](
[TransId] [int] NOT NULL,
[DocId] [int] NOT NULL,
[EmpId] [nvarchar](10) NOT NULL,
[FromToId] [nchar](10) NOT NULL
) ON [PRIMARY]
INSERT INTO [Transaction] ([TransId],[DocId],[EmpId],[FromToId])VALUES(1,1,'Jo','From')
INSERT INTO [Transaction] ([TransId],[DocId],[EmpId],[FromToId])VALUES(2,1,'Fo','To')
INSERT INTO [Transaction] ([TransId],[DocId],[EmpId],[FromToId])VALUES(3,1,'Do','CC')
INSERT INTO [Transaction] ([TransId],[DocId],[EmpId],[FromToId])VALUES(4,2,'Jo','From')
INSERT INTO [Transaction] ([TransId],[DocId],[EmpId],[FromToId])VALUES(5,2,'Bo','To')
INSERT INTO [Transaction] ([TransId],[DocId],[EmpId],[FromToId])VALUES(6,2,'Zo','CC')
INSERT INTO [Transaction] ([TransId],[DocId],[EmpId],[FromToId])VALUES(7,3,'Bo','From')
INSERT INTO [Transaction] ([TransId],[DocId],[EmpId],[FromToId])VALUES(8,3,'Go','To')
Then this query will give you the results you requested:
SELECT DISTINCT
t.DocId
,x.[From]
,y.[To]
,z.Cc
FROM [Transaction] t
LEFT JOIN
(
SELECT DocId
,CASE WHEN FromToId = 'From' THEN EmpId END AS [From]
FROM [Transaction]
WHERE CASE WHEN FromToId = 'From' THEN EmpId END IS NOT NULL
) x ON t.DocId = x.DocId
LEFT JOIN
(
SELECT DocId
,CASE WHEN FromToId = 'To' THEN EmpId END AS [To]
FROM [Transaction]
WHERE CASE WHEN FromToId = 'To' THEN EmpId END IS NOT NULL
) y ON t.DocId = y.DocId
LEFT JOIN
(
SELECT DocId
,CASE WHEN FromToId = 'CC' THEN EmpId END AS [Cc]
FROM [Transaction]
WHERE CASE WHEN FromToId = 'Cc' THEN EmpId END IS NOT NULL
) z ON t.DocId = z.DocId
DocId From To Cc
1 Jo Fo Do
2 Jo Bo Zo
3 Bo Go NULL

Resources