when i run this function
CREATE PROCEDURE alege()
BEGIN
declare v_prenumeNou VARCHAR(15);
declare v_numeRandom INTEGER(10);
declare v_prenumeRandom INTEGER(10);
declare v_idCutremurRandom INTEGER(10);
set v_numeRandom = 1 + CEIL ( RAND() * 50 );
set v_prenumeRandom = 1 + CEIL ( RAND() * 50 );
set v_idCutremurRandom = 1 + CEIL ( RAND() * 50 );
select prenume into v_prenumeNou from (SELECT prenume, rownum as v_rn from voluntari) where v_rn=v_prenumeRandom;
select nume into v_numeNou from (SELECT nume, rownum as v_rn from voluntari) where v_rn=v_numeRandom;
v_idPersoanaNou := v_idPersoanaNou + 1;
INSERT INTO voluntari (IDCUTREMUR, IDPERSOANA, NUME, PRENUME)
VALUES (CONCAT('C',IFNULL(v_idCutremurRandom, '')), CONCAT('V',IFNULL(v_idPersoanaNou, '')) , v_numeNou, v_prenumeNou);
END;
i have this error
[Err] 1248 - Every derived table must have its own alias
how can i solve this ?
You must add an alias to each subquery in your select into statements:
select prenume
into v_prenumeNou
from (SELECT prenume, rownum as v_rn
from voluntari) t1 <-----------
where v_rn=v_prenumeRandom;
select nume
into v_numeNou
from (SELECT nume, rownum as v_rn
from voluntari) t1 <------------
where v_rn=v_numeRandom;
Try with this, just changed the alias of the from clauses (every deribed table must have an alias):
CREATE PROCEDURE alege()
BEGIN
declare v_prenumeNou VARCHAR(15);
declare v_numeRandom INTEGER(10);
declare v_prenumeRandom INTEGER(10);
declare v_idCutremurRandom INTEGER(10);
set v_numeRandom = 1 + CEIL ( RAND() * 50 );
set v_prenumeRandom = 1 + CEIL ( RAND() * 50 );
set v_idCutremurRandom = 1 + CEIL ( RAND() * 50 );
select prenume into v_prenumeNou from (SELECT prenume, rownum as v_rn from voluntari) AS A where v_rn=v_prenumeRandom;
select nume into v_numeNou from (SELECT nume, rownum as v_rn from voluntari) AS B where v_rn=v_numeRandom;
v_idPersoanaNou := v_idPersoanaNou + 1;
INSERT INTO voluntari (IDCUTREMUR, IDPERSOANA, NUME, PRENUME)
VALUES (CONCAT('C',IFNULL(v_idCutremurRandom, '')), CONCAT('V',IFNULL(v_idPersoanaNou, '')) , v_numeNou, v_prenumeNou);
END;
Related
I finally got this function to work correctly until I tried to implement in a production state. When I run this procedure and call, I am only getting a value for the LowerLimit output and a NULL for the UpperLimit output. I added a SELECT in the procedure that shows the results for both the internal variables #lowlim and #upplim are being computed, but it appears that only the set for the LowerLimit variable is working. I've been banging on this for hours and can't figure it out so far. Can anyone see anything obvious I'm missing here?
Here is where the problem is occurring:
SET LowerLimit = #lowlim;
SET UpperLimit = #upplim;
SELECT #lowlim, #upplim;
Here is the full procedure.
DELIMITER $$
DROP PROCEDURE if exists p_GetOutlierLimits;
CREATE DEFINER=`user`#`%` PROCEDURE p_GetOutlierLimits(
IN KPI VARCHAR(255), TableName VARCHAR(100),
OUT LowerLimit decimal(16,6), UpperLimit decimal(16,6)
)
BEGIN
SET #lowlim = 0;
SET #upplim = 0;
SET #SQLExec = CONCAT("
with orderedList AS (
SELECT
",KPI,",
ROW_NUMBER() OVER (ORDER BY ",KPI,") AS row_n
FROM ",TableName,"
),
quartile_breaks AS (
SELECT
",KPI,",
(
SELECT ",KPI," AS quartile_break
FROM orderedList
WHERE row_n = FLOOR((SELECT COUNT(*) FROM ",TableName,")*0.75)
) AS q_three_lower,
(
SELECT ",KPI," AS quartile_break
FROM orderedList
WHERE row_n = FLOOR((SELECT COUNT(*) FROM ",TableName,")*0.75) + 1
) AS q_three_upper,
(
SELECT ",KPI," AS quartile_break
FROM orderedList
WHERE row_n = FLOOR((SELECT COUNT(*) FROM ",TableName,")*0.25)
) AS q_one_lower,
(
SELECT ",KPI," AS quartile_break
FROM orderedList
WHERE row_n = FLOOR((SELECT COUNT(*) FROM ",TableName,")*0.25) + 1
) AS q_one_upper
FROM orderedList
),
iqr AS (
SELECT
",KPI,",
(
(SELECT MAX(q_three_lower)
FROM quartile_breaks) +
(SELECT MAX(q_three_upper)
FROM quartile_breaks)
)/2 AS q_three,
(
(SELECT MAX(q_one_lower)
FROM quartile_breaks) +
(SELECT MAX(q_one_upper)
FROM quartile_breaks)
)/2 AS q_one,
1.5 * ((
(SELECT MAX(q_three_lower)
FROM quartile_breaks) +
(SELECT MAX(q_three_upper)
FROM quartile_breaks)
)/2 - (
(SELECT MAX(q_one_lower)
FROM quartile_breaks) +
(SELECT MAX(q_one_upper)
FROM quartile_breaks)
)/2) AS outlier_range
FROM quartile_breaks
)
SELECT MAX(q_one) OVER () - MAX(outlier_range) OVER () AS lower_limit,
MAX(q_three) OVER () + MAX(outlier_range) OVER () AS upper_limit
INTO #lowlim, #upplim
FROM iqr
LIMIT 1;");
PREPARE stmt FROM #SQLExec;
EXECUTE stmt;
SET LowerLimit = #lowlim;
SET UpperLimit = #upplim;
SELECT #lowlim, #upplim;
END$$
DELIMITER ;
CALL p_GetOutlierLimits('576_VMC_Sol_Savings_Pct','vmctco',#LowerLimit, #UpperLimit);
SELECT #LowerLimit, #UpperLimit;
You need to declare OUT for each parameter:
CREATE DEFINER=`user`#`%` PROCEDURE p_GetOutlierLimits(
IN KPI VARCHAR(255), TableName VARCHAR(100),
OUT LowerLimit decimal(16,6), OUT UpperLimit decimal(16,6)
)
https://dev.mysql.com/doc/refman/8.0/en/create-procedure.html says:
Each parameter is an IN parameter by default. To specify otherwise for a parameter, use the keyword OUT or INOUT before the parameter name.
I want to split the two columns into two rows in a single table separated by ‘;’ in Sql Server 2008. Please help me to resolve to solve this.
Columns like:
1;2;3;4;5;6;7; and a;b;c;d;e;f;g;
Output Rows like:
1 a
2 b
3 c
4 d
5 e
6 f
7 g
First you are going to need a split function as such :
CREATE function [dbo].[Split]
(
#string nvarchar(max),
#delimiter nvarchar(20)
)
returns #table table
(
[Value] nvarchar(max)
)
begin
declare #nextString nvarchar(max)
declare #pos int, #nextPos int
set #nextString = ''
set #string = #string + #delimiter
set #pos = charindex(#delimiter, #string)
set #nextPos = 1
while (#pos <> 0)
begin
set #nextString = substring(#string, 1, #pos - 1)
insert into #table
(
[Value]
)
values
(
#nextString
)
set #string = substring(#string, #pos + len(#delimiter), len(#string))
set #nextPos = #pos
set #pos = charindex(#delimiter, #string)
end
return
end
Then using this code :
SELECT col1.Value as val1,
col2.Value as val2
FROM
(SELECT Value,
ROW_NUMBER() over(order by value asc) as rownum
FROM (
VALUES('1;2;3;4;5;6;7')
) valued(X) CROSS APPLY
DBO.SPLIT(X,';') AS SPLITEDCOL ) as col1 INNER JOIN
(SELECT Value,
ROW_NUMBER() over(order by value asc) as rownum
FROM (
VALUES('A;B;C;D;E;F;G')
) valued1(X) CROSS APPLY
DBO.SPLIT(X,';') AS SPLITEDCOL ) as col2
ON COL1.rownum = col2.rownum
if your two columns are from a table you can select them as such :
SELECT Value,
ROW_NUMBER() over(order by value asc) as rownum
FROM YourTable CROSS APPLY
DBO.SPLIT(YourColumnName,';') AS SPLITEDCOL
Note that 1 subset using cross apply is necessary for each column you want to return in rows
Hope this helps
Declare #ID as Varchar(1000)
set #ID = '1;2;3;4;5;6;7;'
SELECT
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS ID
FROM
(
SELECT CAST('<XMLRoot><RowData>' + REPLACE(#ID,';','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
DECLARE #Table1 TABLE(ID INT, Value char)
INSERT INTO #Table1 VALUES (1,'a'),(1,'b'),(1,'c'),(1,'d')
SELECT STUFF((SELECT '; ' + CAST(ID AS VARCHAR(10)) [text()]
FROM #Table1
WHERE ID = t.ID
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') ID
,STUFF((SELECT '; ' + CAST(Value AS VARCHAR(10)) [text()]
FROM #Table1
WHERE ID = t.ID
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') value
FROM #Table1 t
I need to separate values and store them in different variables in SQL,
for example
a='3100,3101,3102,....'
And the output should be
x=3100
y=3101
z=3102
.
.
.
create function [dbo].[udf_splitstring] (#tokens varchar(max),
#delimiter varchar(5))
returns #split table (
token varchar(200) not null )
as
begin
declare #list xml
select #list = cast('<a>'
+ replace(#tokens, #delimiter, '</a><a>')
+ '</a>' as xml)
insert into #split
(token)
select ltrim(t.value('.', 'varchar(200)')) as data
from #list.nodes('/a') as x(t)
return
end
GO
declare #cad varchar(100)='3100,3101,3102'
select *,ROW_NUMBER() over (order by token ) as rn from udf_splitstring(#cad,',')
token rn
3100 1
3101 2
3102 3
The results of the Parse TVF can easily be incorporated into a JOIN, or an IN
Declare #a varchar(max)='3100,3101,3102'
Select * from [dbo].[udf-Str-Parse](#a,',')
Returns
RetSeq RetVal
1 3100
2 3101
3 3102
The UDF if needed (much faster than recursive, loops, and xml)
CREATE FUNCTION [dbo].[udf-Str-Parse] (#String varchar(max),#Delimiter varchar(25))
Returns Table
As
Return (
with cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (IsNull(DataLength(#String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
cte3(N) As (Select 1 Union All Select t.N+DataLength(#Delimiter) From cte2 t Where Substring(#String,t.N,DataLength(#Delimiter)) = #Delimiter),
cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(#Delimiter,#String,s.N),0)-S.N,8000) From cte3 S)
Select RetSeq = Row_Number() over (Order By A.N)
,RetVal = LTrim(RTrim(Substring(#String, A.N, A.L)))
From cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Much faster than str-Parse, but limited to 8K
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')
I suggest you to use following query, it's much faster than other functions like cross apply and udf.
SELECT
Variables
,S_DATA
FROM (
SELECT
Variables
,CASE WHEN LEN(LIST2)>0 THEN LTRIM(RTRIM(SUBSTRING(LIST2, NUMBER+1, CHARINDEX(',', LIST2, NUMBER+1)-NUMBER - 1)))
ELSE NULL
END AS S_DATA
,NUMBER
FROM(
SELECT Variables
,','+COMMA_SEPARETED_COLUMN+',' LIST2
FROM Tb1
)DT
LEFT OUTER JOIN TB N ON (N.NUMBER < LEN(DT.LIST2)) OR (N.NUMBER=1 AND DT.LIST2 IS NULL)
WHERE SUBSTRING(LIST2, NUMBER, 1) = ',' OR LIST2 IS NULL
) DT2
WHERE S_DATA<>''
and also you should create a table 'NUMBER' before running the above query.
CREATE TABLE TB (Number INT)
DECLARE #I INT=0
WHILE #I<1000
BEGIN
INSERT INTO TB VALUES (#I)
SET #I=#I+1
END
SELECT
PDADate, T.Merchandizer_ID, T.Merchandizer, Merchandizer_LoginName,
STORE_ID, STORE_CODE, STORE_NAME,
ACCOUNT_ID, ACCOUNT_NAME, Account_Store_Format_Id, Account_Store_Format,
StoreType_Id, StoreType, T.Listid, T.Listname,
T.TimeIn, T.TimeOut, T.PlannedDate, T.Reason, TaskCode, TotalTime
FROM
[dbo].Report_RD_Coverage T
INNER JOIN
#TempLocationH TL ON TL.LocationId=T.Location_Id
WHERE
CONVERT(Date, PDADate) Between (#Start_Date) AND Isnull(#End_Date, #CurrentDate)
AND T.Account_Id IN
(SELECT
CASE WHEN #Account_Id IS NULL THEN T.Account_Id
ELSE (SELECT * FROM UDF_SplitString(#Account_Id,','))
END
)
AND T.StoreType_Id IN
(SELECT
CASE WHEN #StoreType_Id IS NULL THEN T.StoreType_Id
ELSE (SELECT * FROM UDF_SplitString(#StoreType_Id,','))
END
)
AND T.Store_Id IN
(SELECT
CASE WHEN #Store_Id IS NULL THEN T.Store_Id
ELSE (SELECT * FROM UDF_SplitString(#Store_Id,','))
END
)
If #Account_Id, #StoreType_Id and #Store_Id are null the it should select all the ACCOUNT_ID, STORETYPE_ID and STORE_ID otherwise based on parameter value it should filter.
UDF_SplitString is the function to split up comma-separated strings, and its return value is a table like:
- 1
- 2
- 3
I'm getting this error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
CASE must return a scalar value, so try this variation instead:
select PDADate, T.Merchandizer_ID, T.Merchandizer, Merchandizer_LoginName, STORE_ID, STORE_CODE,
STORE_NAME, ACCOUNT_ID, ACCOUNT_NAME, Account_Store_Format_Id, Account_Store_Format,
StoreType_Id, StoreType, T.Listid, T.Listname, T.TimeIn, T.TimeOut, T.PlannedDate,
T.Reason, TaskCode, TotalTime
from [dbo].Report_RD_Coverage T
inner join #TempLocationH TL on TL.LocationId = T.Location_Id
where CONVERT(date, PDADate) between (#Start_Date)
and Isnull(#End_Date, #CurrentDate)
and (
#Account_Id is null
or T.Account_Id in (
select *
from UDF_SplitString(#Account_Id, ',')
)
)
and (
#StoreType_Id is null
or T.StoreType_Id in (
select *
from UDF_SplitString(#StoreType_Id, ',')
)
)
and (
#Store_Id is null
or T.Store_Id in (
select *
from UDF_SplitString(#Store_Id, ',')
) end
)
I tried this and reached very closer but you have to do something from what I found a link.
This is my try. the only thing you need to build is the #udf data.
declare #Store_Id INT;
declare #Account_Id INT;
DECLARE #UDF[9] OF VARCHAR(30);
set #Store_Id = 99 --NULL
set #Account_Id = 15
SET #UDF = '11,12,13,14,15,16'
SELECT #Account_Id AS ACID
WHERE CAST(#Account_Id AS VARCHAR(6)) IN (
CASE WHEN #Store_Id IS NULL THEN CAST(#Account_Id AS VARCHAR(6))
ELSE #UDF END
The link is at
http://www.codeproject.com/Questions/473174/CreateplusArrayplusinplusSqlplusServer
DECLARE #INSTR as VARCHAR(MAX)
SET #INSTR = '2,3,177,'
DECLARE #SEPERATOR as VARCHAR(1)
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
SET #SEPERATOR = ','
CREATE TABLE #tempTab (id int not null)
WHILE PATINDEX('%' + #SEPERATOR + '%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%' + #SEPERATOR + '%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #tempTab (id) VALUES (#VALUE)
END
SELECT * FROM myTable WHERE id IN **(SELECT id FROM #tempTab)**
DROP TABLE #tempTab
you can extract for the sql in bold and the logic how to create temp table and its data and I hope you will get what you want.
> This is the my right solultion........now its working correctly
CREATE TABLE #Store_Id (StoreID varchar(20))
IF #Store_Id != '0'
BEGIN
INSERT INTO #Store_Id
SELECT data FROM UDF_SplitString(#Store_Id,',')
END
ELSE
BEGIN
INSERT INTO #Store_Id
SELECT '0'
END
CREATE TABLE #StoreType_Id (StoreTypeID varchar(20))
IF #StoreType_Id != '0'
BEGIN
INSERT INTO #StoreType_Id
SELECT data FROM UDF_SplitString(#StoreType_Id,',')
END
ELSE
BEGIN
INSERT INTO #StoreType_Id
SELECT '0'
END
CREATE TABLE #Account_Id (AccountID varchar(20))
IF #Account_Id != '0'
BEGIN
INSERT INTO #Account_Id
SELECT data FROM UDF_SplitString(#Account_Id,',')
END
ELSE
BEGIN
INSERT INTO #Account_Id
SELECT '0'
END
INSERT INTO #FinalTable(VisitDate,Merchandizer_Id,Merchandizer,MerchandizerLogin,StoreId,StoreCode,StoreName,AccountId,AccountName,
Account_Store_Format_Id,Account_Store_Format,StoreTypeId ,StoreType ,ListId ,ListName,TimeIn ,TimeOut,PlannedDate ,Reason ,TaskCode,TotalTime)
SELECT Visit_Date,T.Merchandizer_ID,T.Merchandizer,Merchandizer_LoginName,STORE_ID,STORE_CODE,STORE_NAME,ACCOUNT_ID,ACCOUNT_NAME,
Account_Store_Format_Id,Account_Store_Format,StoreType_Id,
StoreType,T.Listid,T.Listname,T.TimeIn,T.TimeOut,T.PlannedDate,T.Reason,TaskCode,TotalTime
FROM [dbo].Report_RD_Coverage T
INNER JOIN #TempLocationH TL ON TL.LocationId=T.Location_Id
INNER JOIN #Store_Id on CONVERT(VARCHAR,t.Store_Id) = CASE WHEN #Store_Id = '0' THEN convert(VARCHAR,t.Store_Id) ELSE StoreID END
INNER JOIN #StoreType_Id on CONVERT(VARCHAR,t.StoreType_Id) = CASE WHEN #StoreType_Id = '0' THEN convert(VARCHAR,t.StoreType_Id) ELSE StoreTypeID END
INNER JOIN #Account_Id on CONVERT(VARCHAR,t.Account_Id) = CASE WHEN #Account_Id = '0' THEN convert(VARCHAR,t.Account_Id) ELSE AccountID END
WHERE CONVERT(Date,PDADate) Between #Start_Date AND #End_Date
I have a query that outputs just one row of data. I want to convert that row to column and the column to row.
My original query
------------------------
ID Name Desc
------------------------
1 Nisha Some desc
what I need
--------------------------
FieldName FieldValue
--------------------------
ID 1
Name Nisha
Description Some Desc
declare #colNum int, #i int = 1, #a nvarchar(4000)
select #colNum=count(COLUMN_NAME) from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'YourTable'
set #a = '
declare #tempTable table
(
slno int
,field nvarchar(100)
,value nvarchar(100)
)
insert into #tempTable (slno,field)
select ROW_NUMBER() over (order by ordinal_position asc),COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ''YourTable''
declare #p nvarchar(100)
'
declare #colname nvarchar(100)
while #i<=#colNum
begin
select #colname =a.COLUMN_NAME from (select COLUMN_NAME,ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'YourTable'
)as a
where a.ORDINAL_POSITION = #i
set #a = #a + '
select #p='+#colname+' from YourTable
update #tempTable set
value = #p
where slno = '+CONVERT(nvarchar(5), #i)
+'
'
set #i=#i+1
end
set #a = #a + ' select * from #tempTable'
declare #tempTable table
(
slno int
,field nvarchar(100)
,value nvarchar(100)
)
insert into #tempTable exec (#a)
select * from YourTable
select * from #tempTable