How do I replace non-existent records with not found in the following query. Right now I'm just getting the records that are found.
SELECT CASE WHEN `Name` IS NOT NULL THEN `Name` ELSE 'Not Found' END AS Name
FROM `studentDetails`
WHERE `Transaction_ID` IN('496018490c1d5d60beb5', '77888f084c8a0e7578f5')
My input is
'496018490c1d5d60beb5',
'77888f084c8a0e7578f5'
What I'm getting is
Vinod Tonde
My desired output is
Not Found
Vinod Tonde
The Database looks like
I think what you want is this:
SELECT Transaction_ID, CASE WHEN count(*)>0 THEN `Name` ELSE 'Not Found' END AS Name
FROM `studentDetails`
WHERE `Transaction_ID` IN('496018490c1d5d60beb5', 'b6836a07a3c49af6187f')
group by Transaction_ID
OR, using this you could also try:
SELECT IFNULL(Name, 'Not Found') AS Name
FROM (SELECT '496018490c1d5d60beb5' as col
union all
SELECT 'b6836a07a3c49af6187f') temp_table
LEFT JOIN studentDetails
ON temp_table.col=studentDetails.Transaction_ID collate utf8mb4_unicode_ci
Try this:
UPDATE `studentDetails` SET `Name` = 'Not Found' WHERE (`Name` IS NULL OR `Name` = '') AND `Transaction_ID` IN('496018490c1d5d60beb5', 'b6836a07a3c49af6187f')
You can add a few more alternatives to your case
SELECT CASE
WHEN Name IS NULL THEN 'Not Found'
WHEN length(trim(Name)) = 0 THEN 'Not Found'
ELSE Name
END AS Name
FROM studentDetails
WHERE Transaction_ID IN('496018490c1d5d60beb5', 'b6836a07a3c49af6187f')
Edit
Since it seems that one of those two transaction_id doesn't exist in the database at all, you probably need something like this instead
select coalesce(t2.Name, 'Not Found') as Name
from (select '77888f084c8a0e7578f5' as trans union all select '496018490c1d5d60beb5') t1
left join
studentDetails t2
on t1.trans = t2.Transaction_ID
Create a table for the ids to search:
CREATE TABLE ids (id VARCHAR(30));
Create a procedure to split a list of ids separated by a ',' and insert them into the ids table:
CREATE PROCEDURE split_id_list(IN input VARCHAR(300))
BEGIN
DECLARE tot_length int;
DECLARE sub_length int;
my_loop: LOOP
SET tot_length = CHAR_LENGTH(input);
INSERT INTO ids (id) VALUES(SUBSTRING_INDEX(input, ',', 1));
SET sub_length = CHAR_LENGTH(SUBSTRING_INDEX(input, ',', 1))+2;
SET input = MID(input, sub_length, tot_length);
IF input = '' THEN
LEAVE my_loop;
END IF;
END LOOP my_loop;
END;
Create a procedure to generate view containing the results:
CREATE PROCEDURE idsNames(IN id_list VARCHAR(500))
BEGIN
DECLARE a INT;
DECLARE cur1 CURSOR for select count(*) FROM ids;
OPEN cur1;
FETCH cur1 into a;
IF a > 0
THEN DELETE FROM ids;
END IF;
CLOSE cur1;
call split_id_list(id_list);
CREATE OR REPLACE VIEW RESULTS(r_id,r_name) AS
(SELECT ids.id, CASE WHEN Name IS NULL then 'NotFound' ELSE Name END
FROM studentDetails
RIGHT JOIN ids
ON studentDetails.Transaction_ID = ids.id);
END;
Once the table and the procedures are created, each time you want to execute them, just execute the procedure with the required ids and a select from the view:
CALL idsNames('496018490c1d5d60beb5,b6836a07a3c49af6187f');
SELECT r_name FROM RESULTS;
SELECT IF((
SELECT COUNT(TABLE_NAME)
FROM information_schema.tables
WHERE TABLE_SCHEMA='database0' AND TABLE_NAME='table'
) >0 , (
SELECT id
FROM database1.table
WHERE id NOT IN (SELECT id FROM database0.table)
), NULL) AS pk_value;
The table database0.table may not exist; if the table does not exist, I want to skip the true clause of the IF statement. Even when the IF statement should return NULL, I get the error that database0.table does not exist. What can I do so that the query returns NULL instead of throwing an error if the table does not exist?
As mentioned in comments, queries are error-checked before they are run, so referring to a non-existent table won't work. You can store it as a function, which is only evaluated at run-time:
DROP FUNCTION IF EXISTS get_pk;
DELIMITER //
CREATE FUNCTION get_pk()
RETURNS INT
BEGIN
DECLARE counter INT;
DECLARE pk_value INT;
SELECT COUNT(table_name) INTO counter
FROM information_schema.tables
WHERE table_schema = 'database0' AND table_name = 'table';
IF counter = 1 THEN
SELECT id INTO pk_value
FROM database1.table
WHERE id NOT IN (SELECT id FROM database0.table);
ELSE
SELECT NULL INTO pk_value;
END IF;
RETURN pk_value;
END//
DELIMITER ;
Then access the value like this:
SELECT get_pk();
When i run this code, it gives me error. From this code, there's several task to do:
(1) update tble customer by setting the address to '90 TYT' if c_id= 1
(2) view order_no,status,c_id,item_total remarks.
(3) if item_total 0, then update table order_status by setting remarks = 'UNAVAILABLE', else select order_no,status,item_total,remarks where status = 'waiting'.
Please help me fix the error. I'm new to SQL.
#drop procedure if exists usp_GetAnything;
delimiter //
create procedure usp_GetAnything()
begin
select c_id,lname,address,city
from customer;
update customer
set address = '90 TYT'
where c_id = 1;
select o.order_no,o.o_status,c.c_id,o.item_total,o.remarks
from customer c, order_status o
where c.c_id=o.c_id;
if (o.item_total > 0) then
update order_status o
set remarks = 'UNAVAILABLE'
where order_no > '123';
else
select order_no,o_status,item_total,remarks
from order_status
where o_status = 'waiting';
end if;
end
It's failing on the line:
if (o.item_total > 0)
o is unidentified outside of the previous select clause including all the selected variables.
In order to use the results that returned from the previous select you should select ... INTO...
(select the result arguments into declared local variables).
You can find here the following example:
DELIMITER //
CREATE PROCEDURE `proc_WHILE` (IN param1 INT)
BEGIN
DECLARE variable1, variable2 INT;
SET variable1 = 0;
WHILE variable1 < param1 DO
INSERT INTO table1 VALUES (param1);
SELECT COUNT(*) INTO variable2 FROM table1;
SET variable1 = variable1 + 1;
END WHILE;
END //
You can see that variable1 and variable2 are declared in the beginning of the procedure and later on used with select ... INTO ....
BEGIN
CASE x
WHEN 0 THEN (
IF thisIsAVariable = 'viewAll' THEN
SELECT id, fname FROM Persons WHERE 1
ELSE
SELECT id, fname FROM Persons WHERE id = '1111'
END IF
);
END CASE;
END
What is the correct syntax for ifelse statments inside casewhen statements?
we can use if inside the if to make code easy like below:
BEGIN
IF x = 0 THEN
IF thisIsAVariable = 'viewAll' THEN
SELECT id, fname FROM Persons WHERE 1;
ELSE
SELECT id, fname FROM Persons WHERE id = '1111';
END IF;
END IF;
END
just use IF-ELSE,
DELIMITER $$
CREATE PROCEDURE procName
BEGIN
IF x = 0 THEN
IF thisIsAVariable = 'viewAll' THEN
SELECT id, fname FROM Persons WHERE 1;
ELSE
SELECT id, fname FROM Persons WHERE id = '1111';
END IF;
ELSE
-- other codes if you have
END IF;
END $$
DELIMITER ;
I think when using CASE, the select statement should return only one value.
just try this one
BEGIN
CASE x
WHEN 0 THEN (
SELECT id, fname FROM Persons WHERE id = IF(thisIsAVariable = 'viewAll',1,'1111')
);
END CASE;
END
I have the following table with each row having comma-separated values:
ID
-----------------------------------------------------------------------------
10031,10042
10064,10023,10060,10065,10003,10011,10009,10012,10027,10004,10037,10039
10009
20011,10027,10032,10063,10023,10033,20060,10012,10020,10031,10011,20036,10041
I need to get a count for each ID (a groupby).
I am just trying to avoid cursor implementation and stumped on how to do this without cursors.
Any Help would be appreciated !
You will want to use a split function:
create FUNCTION [dbo].[Split](#String varchar(MAX), #Delimiter char(1))
returns #temptable TABLE (items varchar(MAX))
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end;
And then you can query the data in the following manner:
select items, count(items)
from table1 t1
cross apply dbo.split(t1.id, ',')
group by items
See SQL Fiddle With Demo
Well, the solution i always use, and probably there might be a better way, is to use a function that will split everything. No use for cursors, just a while loop.
if OBJECT_ID('splitValueByDelimiter') is not null
begin
drop function splitValueByDelimiter
end
go
create function splitValueByDelimiter (
#inputValue varchar(max)
, #delimiter varchar(1)
)
returns #results table (value varchar(max))
as
begin
declare #delimeterIndex int
, #tempValue varchar(max)
set #delimeterIndex = 1
while #delimeterIndex > 0 and len(isnull(#inputValue, '')) > 0
begin
set #delimeterIndex = charindex(#delimiter, #inputValue)
if #delimeterIndex > 0
set #tempValue = left(#inputValue, #delimeterIndex - 1)
else
set #tempValue = #inputValue
if(len(#tempValue)>0)
begin
insert
into #results
select #tempValue
end
set #inputValue = right(#inputValue, len(#inputValue) - #delimeterIndex)
end
return
end
After that you can call the output like this :
if object_id('test') is not null
begin
drop table test
end
go
create table test (
Id varchar(max)
)
insert
into test
select '10031,10042'
union all select '10064,10023,10060,10065,10003,10011,10009,10012,10027,10004,10037,10039'
union all select '10009'
union all select '20011,10027,10032,10063,10023,10033,20060,10012,10020,10031,10011,20036,10041'
select value
from test
cross apply splitValueByDelimiter(Id, ',')
Hope it helps, although i am still looping through everything
After reiterating the comment above about NOT putting multiple values into a single column (Use a separate child table with one value per row!),
Nevertheless, one possible approach: use a UDF to convert delimited string to a table. Once all the values have been converted to tables, combine all the tables into one table and do a group By on that table.
Create Function dbo.ParseTextString (#S Text, #delim VarChar(5))
Returns #tOut Table
(ValNum Integer Identity Primary Key,
sVal VarChar(8000))
As
Begin
Declare #dlLen TinyInt -- Length of delimiter
Declare #wind VarChar(8000) -- Will Contain Window into text string
Declare #winLen Integer -- Length of Window
Declare #isLastWin TinyInt -- Boolean to indicate processing Last Window
Declare #wPos Integer -- Start Position of Window within Text String
Declare #roVal VarChar(8000)-- String Data to insert into output Table
Declare #BtchSiz Integer -- Maximum Size of Window
Set #BtchSiz = 7900 -- (Reset to smaller values to test routine)
Declare #dlPos Integer -- Position within Window of next Delimiter
Declare #Strt Integer -- Start Position of each data value within Window
-- -------------------------------------------------------------------------
-- ---------------------------
If #delim is Null Set #delim = '|'
If DataLength(#S) = 0 Or
Substring(#S, 1, #BtchSiz) = #delim Return
-- --------------------------------------------
Select #dlLen = DataLength(#delim),
#Strt = 1, #wPos = 1,
#wind = Substring(#S, 1, #BtchSiz)
Select #winLen = DataLength(#wind),
#isLastWin = Case When DataLength(#wind) = #BtchSiz
Then 0 Else 1 End,
#dlPos = CharIndex(#delim, #wind, #Strt)
-- --------------------------------------------
While #Strt <= #winLen
Begin
If #dlPos = 0 Begin -- No More delimiters in window
If #isLastWin = 1 Set #dlPos = #winLen + 1
Else Begin
Set #wPos = #wPos + #Strt - 1
Set #wind = Substring(#S, #wPos, #BtchSiz)
-- ----------------------------------------
Select #winLen = DataLength(#wind), #Strt = 1,
#isLastWin = Case When DataLength(#wind) = #BtchSiz
Then 0 Else 1 End,
#dlPos = CharIndex(#delim, #wind, 1)
If #dlPos = 0 Set #dlPos = #winLen + 1
End
End
-- -------------------------------
Insert #tOut (sVal)
Select LTrim(Substring(#wind,
#Strt, #dlPos - #Strt))
-- -------------------------------
-- Move #Strt to char after last delimiter
Set #Strt = #dlPos + #dlLen
Set #dlPos = CharIndex(#delim, #wind, #Strt)
End
Return
End
Then write, (using your table schema),
Declare #AllVals VarChar(8000)
Select #AllVals = Coalesce(#allVals + ',', '') + ID
From Table Where ID Is Not null
-- -----------------------------------------
Select sVal, Count(*)
From dbo.ParseTextString(#AllVals, ',')
Group By sval