My data looks like this,
I have multiple values in the Table field with each having its own unique values for the Data field. However, Data values for TableA will be the same format in the table myTable. Same applies to all records in the Table field.
I am using JSON_EXTRACT to get the value in conjunction with CASE statements.
SELECT
CASE
WHEN
Table = 'table A'
THEN
CONCAT_WS('\n','Name: ',
JSON_EXTRACT(Data, '$.name'))
END AS 'tableA',
CASE
WHEN
Table = 'table B'
THEN
CONCAT_WS('\n','Location: ',
JSON_EXTRACT(Data, '$.fieldType'))
END AS 'tableB' from myTable
The problem with this is that I will be getting null values.
I am getting the below results,
I am expecting the below results,
I want to avoid the null values. Is there any other way to extract the data ? I am using MYSQL.
Option one:
Select *
from ( SELECT CASE WHEN Table_c = 'table A' THEN
CONCAT_WS('\n','Name: ', JSON_EXTRACT(data_c, '$.name'))
END AS 'TableA'
from test_t) A,
( SELECT CASE WHEN Table_c = 'table B' THEN
CONCAT_WS('\n','Location: ', JSON_EXTRACT(data_c, '$.fieldType'))
END AS 'TableB'
from test_t) B
where TableA is not null
and TableB is not null
Option two:
SELECT CASE WHEN Table_c = 'table B' THEN
CONCAT_WS('\n','Location: ', JSON_EXTRACT(data_c, '$.fieldType'))
ELSE
CONCAT_WS('\n','Name: ', JSON_EXTRACT(data_c, '$.name'))
END AS 'Data'
, CASE WHEN Table_c = 'table B' THEN
'Table B'
ELSE
'Table A'
END AS 'Table'
from test_t
Here is the demo
Please note that I have changed the names of the table and columns in my demo.
I think you just want conditional aggregation:
SELECT MAX(CASE WHEN Table = 'table A'
THEN CONCAT_WS('\n', 'Name: ', JSON_EXTRACT(Data, '$.name'))
END) AS tableA,
MAX(CASE WHEN Table = 'table B'
THEN CONCAT_WS('\n','Location: ', JSON_EXTRACT(Data, '$.fieldType'))
END) AS tableB
from myTable;
If there could be multiple matches in the JSON, then you might want GROUP_CONCAT() instead:
SELECT GROUP_CONCAT(CASE WHEN Table = 'table A'
THEN CONCAT_WS('\n', 'Name: ', JSON_EXTRACT(Data, '$.name'))
END) AS tableA,
GROUP_CONCAT(CASE WHEN Table = 'table B'
THEN CONCAT_WS('\n','Location: ', JSON_EXTRACT(Data, '$.fieldType'))
END) AS tableB
from myTable;
Note: you have to understand these are not actual null values in database but because your requirement is to read and convert the rows to columns and thus each row in the final result will have null value for all columns other than the corresponding derived one. We can use max on each column (each "CASE" as in your query).
You could try with below,
SELECT MAX(IF(data_type = 'TableA', CONCAT_WS('\n', 'Name: ',
JSON_EXTRACT(data, '$.name'))
, ''))
TableA,
MAX(IF(data_type = 'TableB', CONCAT_WS('\n', 'Location: ',
JSON_EXTRACT(data, '$.fieldType')), ''))
TableB
FROM mytable
can someone please tell me what I am missing I have invested 4 hours and watch lots of article can't figure out why is showing return null
mysql mysql procedure is as follows.
create procedure proc_studymaterial_listing(
get_exam_id int(11)
)
begin
set #query1 = concat( "select c.content_type,
c.title,
c.status,
c.created_on,
c.pdf_is_downloadable,
a.content_id,
a.expiry_date,
exam_Name,
fun_subject_name(a.subject_id) as subject_name,
fun_subject_name(a.chapter_id) as chapter_name
from tbl_studymaterial_exam_chapter_map as a
join tbl_exam_master as b on a.exam_id= b.exam_ID
join tbl_studymaterial as c on c.id= a.content_id
where c.status=1 " );
if( get_exam_id = 0 )
then
set #exam_id = " and 1=1 ";
else
set #exam_id = concat( ' and b.exam_ID = " ', #get_exam_id , '"' );
end if;
SET #final_query = CONCAT ( #query1,#exam_id );
PREPARE stmt FROM #final_query ;
# select stmt;
# EXECUTE stmt;
# DEALLOCATE PREPARE stmt;
end;
User-defined variable #get_exam_id doesn't appear to be assigned a value anywhere. If that's not assigned a non-NULL value, then the result of evaluating this line:
set #exam_id = concat( ' and b.exam_ID = " ', #get_exam_id , '"' );
is that #exam_id will be NULL. And that will cascade into the next CONCAT, which will also evaluate to NULL.
User-defined variables start with an # at sign character.
Those are distinct and separate from procedure arguments and variables, which do not start with an # at sign character.
Looks like maybe the intent was to reference the local variable get_exam_id, not a user-defined variable.
FOLLOWUP
Personally, if I had to write the body of the procedure, I'd do it something like this:
DELIMITER $$
CREATE PROCEDURE proc_studymaterial_listing( get_exam_id INT(11))
BEGIN
SET #sql = CONCAT( 'SELECT c.content_type'
,'\n' ,' , c.title'
,'\n' ,' , c.status'
,'\n' ,' , c.created_on'
,'\n' ,' , c.pdf_is_downloadable'
,'\n' ,' , a.content_id'
,'\n' ,' , a.expiry_date'
,'\n' ,' , b.exam_name'
,'\n' ,' , fun_subject_name(a.subject_id) AS subject_name'
,'\n' ,' , fun_subject_name(a.chapter_id) AS chapter_name'
,'\n' ,' FROM tbl_studymaterial_exam_chapter_map a'
,'\n' ,' JOIN tbl_exam_master b'
,'\n' ,' ON b.exam_id = a.exam_id'
,'\n' ,' JOIN tbl_studymaterial c'
,'\n' ,' ON c.id = a.content_id'
,'\n' ,' WHERE c.status = 1'
,'\n'
,CASE
WHEN get_exam_id <> 0
THEN ' AND b.exam_id = ? '
ELSE ''
END
,'\n' ,' ORDER BY subject_name, chapter_name, exam_name'
);
PREPARE stmt FROM #sql;
IF (get_exam_id <> 0) THEN
SET #id = get_exam_id;
EXECUTE stmt USING #id;
SET #id = '';
ELSE
EXECUTE stmt;
END IF;
DEALLOCATE PREPARE stmt;
SET #sql = '';
END;
$$
DELIMITER ;
SELECT
`BillNum`
, GROUP_CONCAT(CONCAT( `City` , ' / ' , `Region` , ' / ' , `StreetName` , ' / ' , `Closepoint`)) AS 'Address'
, GROUP_CONCAT(CONCAT('(', `ItemCount` ,')', `ItemName` , ' ' )separator ' ') AS OrderInfo
, CustomerPhone , `OrderTime`
FROM orderin
INNER JOIN `customers`
WHERE `CustomerPhone` = `customers`.`PhoneNumber`
AND `TableNum` = '0' AND DeleveryState = '0'
GROUP BY `BillNum`
ORDER BY `BillNum`;
Where is this wrong ? Why the address is multiplied ?
Add Distinct to your Group_Concat
Like
SELECT
`BillNum`
, GROUP_CONCAT(DISTINCT CONCAT( `City` , ' / ' , `Region` , ' / ' , `StreetName` , ' / ' , `Closepoint`)) AS 'Address'
, GROUP_CONCAT(DISTINCT CONCAT('(', `ItemCount` ,')', `ItemName` , ' ' )separator ' ') AS OrderInfo
, CustomerPhone , `OrderTime`
FROM orderin INNER JOIN `customers`
WHERE `CustomerPhone` = `customers`.`PhoneNumber`
AND `TableNum` = '0' AND DeleveryState = '0'
GROUP BY `BillNum`
ORDER BY `BillNum`
How can I get a column from the top-most parent query in a subquery within a subquery? Do I have to pass it like a variable? Here's my code:
SELECT c.in_customer_id,
(
SELECT
group_concat(the_schedule separator '\r\n')
FROM
(
SELECT
concat_ws('\n', 'Route: ', s.route_id, 'Interval: ', s.service_interval, 'Week No.: ', s.week_no, 'Weekdays: ', s.weekdays, 'Start Date: ', s.start_date, 'End Date: ', s.end_date, 'Start Time: ', s.start_time, 'End Time: ', s.end_time, '\n') AS the_schedule
FROM
schedule s
WHERE
s.service_address_id IN
(
SELECT in_customer_address_id
FROM tbl_customer_address a2
WHERE a2.in_customer_id = c.in_customer_id
)
AND s.is_skipped = '0'
GROUP BY
s.service_address_id
) a
)
AS "Schedule"
FROM
tbl_customers c
The response I get is "Error Code: 1054. Unknown column 'c.in_customer_id' in 'where clause'"
As a principle, you want to move the sub-queries in to your FROM clause.
Try something like this...
SELECT
c.in_customer_id,
s.grouped_schedule
FROM
tbl_customers AS c
LEFT JOIN
(
SELECT
in_customer_id,
group_concat(the_schedule separator '\r\n') AS grouped_schedule
FROM
(
SELECT
a.in_customer_id,
a.in_customer_address_id,
concat_ws('\n', 'Route: ', s.route_id, 'Interval: ', s.service_interval, 'Week No.: ', s.week_no, 'Weekdays: ', s.weekdays, 'Start Date: ', s.start_date, 'End Date: ', s.end_date, 'Start Time: ', s.start_time, 'End Time: ', s.end_time, '\n') AS the_schedule
FROM
tbl_customer_address AS a
INNER JOIN
schedule AS s
ON s.service_address_id = a.in_customer_address_id
WHERE
s.is_skipped = 0
)
AS schedules
GROUP BY
in_cusomer_id
)
AS s
ON s.in_customer_id = c.in_customer_id
I have a column which has FirstName and LastName together. I'm writing a report to separate the FirstName And LastName. How do I get the FirstName and LastName separated in T-SQL?
Assuming the FirstName is all of the characters up to the first space:
SELECT
SUBSTRING(username, 1, CHARINDEX(' ', username) - 1) AS FirstName,
SUBSTRING(username, CHARINDEX(' ', username) + 1, LEN(username)) AS LastName
FROM
whereever
The easiest way I can find to do it is:
SELECT
SUBSTRING(FullName, 1, CHARINDEX(' ', FullName) - 1) AS FirstName,
REVERSE(SUBSTRING(REVERSE(FullName), 1, CHARINDEX(' ', REVERSE(FullName)) - 1)) AS LastName
FROM
[PERSON_TABLE]
This should work:
Select
LTRIM(RTRIM(SUBSTRING(FullName, 0, CHARINDEX(' ', FullName)))) As FirstName
, LTRIM(RTRIM(SUBSTRING(FullName, CHARINDEX(' ', FullName)+1, 8000)))As LastName
FROM TABLE
Edit: Adopted Aaron's and Jonny's hint with the fixed length of 8000 to avoid unnecessary calculations.
validate last name is blank
SELECT
person.fullName,
(CASE WHEN 0 = CHARINDEX(' ', person.fullName)
then person.fullName
ELSE SUBSTRING(person.fullName, 1, CHARINDEX(' ', person.fullName)) end) as first_name,
(CASE WHEN 0 = CHARINDEX(' ', person.fullName)
THEN ''
ELSE SUBSTRING(person.fullName,CHARINDEX(' ', person.fullName), LEN(person.fullName) )end) last_name
FROM person
Here is a more elaborated solution with a SQL function:
GetFirstname
CREATE FUNCTION [dbo].[ufn_GetFirstName]
(
#FullName varchar(500)
)
RETURNS varchar(500)
AS
BEGIN
-- Declare the return variable here
DECLARE #RetName varchar(500)
SET #FullName = replace( replace( replace( replace( #FullName, '.', '' ), 'Mrs', '' ), 'Ms', '' ), 'Mr', '' )
SELECT
#RetName =
CASE WHEN charindex( ' ', ltrim( rtrim( #FullName ) ) ) > 0 THEN left( ltrim( rtrim( #FullName ) ), charindex( ' ', ltrim( rtrim( #FullName ) ) ) - 1 ) ELSE '' END
RETURN #RetName
END
GetLastName
CREATE FUNCTION [dbo].[ufn_GetLastName]
(
#FullName varchar(500)
)
RETURNS varchar(500)
AS
BEGIN
DECLARE #RetName varchar(500)
IF(right(ltrim(rtrim(#FullName)), 2) <> ' I')
BEGIN
set #RetName = left(
CASE WHEN
charindex( ' ', reverse( ltrim( rtrim(
replace( replace( replace( replace( replace( replace( #FullName, ' Jr', '' ), ' III', '' ), ' II', '' ), ' Jr.', '' ), ' Sr', ''), 'Sr.', '')
) ) ) ) > 0
THEN
right( ltrim( rtrim(
replace( replace( replace( replace( replace( replace( #FullName, ' Jr', '' ), ' III', '' ), ' II', '' ), ' Jr.', '' ), ' Sr', ''), 'Sr.', '')
) ) , charindex( ' ', reverse( ltrim( rtrim(
replace( replace( replace( replace( replace( replace( #FullName, ' Jr', '' ), ' III', '' ), ' II', '' ), ' Jr.', '' ), ' Sr', ''), 'Sr.', '')
) ) ) ) - 1 )
ELSE '' END
, 25 )
END
ELSE
BEGIN
SET #RetName = left(
CASE WHEN
charindex( ' ', reverse( ltrim( rtrim(
replace( replace( replace( replace( replace( replace( replace( #FullName, ' Jr', '' ), ' III', '' ), ' II', '' ), ' I', '' ), ' Jr.', '' ), ' Sr', ''), 'Sr.', '')
) ) ) ) > 0
THEN
right( ltrim( rtrim(
replace( replace( replace( replace( replace( replace( replace( #FullName, ' Jr', '' ), ' III', '' ), ' II', '' ), ' I', '' ), ' Jr.', '' ), ' Sr', ''), 'Sr.', '')
) ) , charindex( ' ', reverse( ltrim( rtrim(
replace( replace( replace( replace( replace( replace( replace( #FullName, ' Jr', '' ), ' III', '' ), ' II', '' ), ' I', '' ), ' Jr.', '' ), ' Sr', ''), 'Sr.', '')
) ) ) ) - 1 )
ELSE '' END
, 25 )
END
RETURN #RetName
END
USE:
SELECT dbo.ufn_GetFirstName(Fullname) as FirstName, dbo.ufn_GetLastName(Fullname) as LastName FROM #Names
You could do this if firstname and surname are separated by space:
SELECT SUBSTRING(FirstAndSurnameCol, 0, CHARINDEX(' ', FirstAndSurnameCol)) Firstname,
SUBSTRING(FirstAndSurnameCol, CHARINDEX(' ', FirstAndSurnameCol)+1, LEN(FirstAndSurnameCol)) Surname FROM ...
This will take care of names like "Firstname Z. Lastname" and "First Z Last"
SELECT
CASE
WHEN CHARINDEX(' ',name) = 0 THEN name
WHEN CHARINDEX(' ',name) = PATINDEX('% _[., ]%',name) THEN RTRIM(SUBSTRING(name, 1, CHARINDEX(' ',name) + 2))
ELSE SUBSTRING(name,1, CHARINDEX(' ',name))
END [firstname]
,CASE
WHEN CHARINDEX(' ',name) = 0 THEN ''
WHEN CHARINDEX(' ',name) = PATINDEX('% _[., ]%',name) THEN LTRIM(SUBSTRING(name, CHARINDEX(' ',name) + 3,1000))
ELSE SUBSTRING(name,CHARINDEX(' ',name)+1,1000)
END [lastname]
FROM [myTable]
I think below query will be helpful to split FirstName and LastName from FullName even if there is only FirstName.
For example: 'Philip John' can be split into Philip and John.
But if there is only Philip, because of the charIndex of Space is 0, it will only give you ''.
Try the below one.
declare #FullName varchar(100)='Philp John'
Select
LTRIM(RTRIM(SUBSTRING(#FullName, 0, CHARINDEX(' ', #FullName+' ')))) As FirstName
, LTRIM(RTRIM(SUBSTRING(#FullName, CHARINDEX(' ', #FullName+' ')+1, 8000)))As LastName
Hope this will help you. :)
You may have problems if the Fullname doesn't contain a space.
Assuming the whole of FullName goes to Surname if there is no space and FirstName becomes an empty string, then you can use this:
SELECT
RTRIM(LEFT(FullName, CHARINDEX(' ', FullName))) AS FirstName,
SUBSTRING(FullName, CHARINDEX(' ', FullName) + 1, 8000) AS LastName
FROM
MyNameTable;
The code below works with Last, First M name strings. Substitute "Name" with your name string column name. Since you have a period as a final character when there is a middle initial, you would replace the 2's with 3's in each of the lines (2, 6, and 8)- and change "RIGHT(Name, 1)" to "RIGHT(Name, 2)" in line 8.
SELECT SUBSTRING(Name, 1, CHARINDEX(',', Name) - 1) LastName ,
CASE WHEN LEFT(RIGHT(Name, 2), 1) <> ' '
THEN LTRIM(SUBSTRING(Name, CHARINDEX(',', Name) + 1, 99))
ELSE LEFT(LTRIM(SUBSTRING(Name, CHARINDEX(',', Name) + 1, 99)),
LEN(LTRIM(SUBSTRING(Name, CHARINDEX(',', Name) + 1, 99)))
- 2)
END FirstName ,
CASE WHEN LEFT(RIGHT(Name, 2), 1) = ' ' THEN RIGHT(Name, 1)
ELSE NULL
END MiddleName
For the last name as in US standards (i.e., last word in the [Full Name] column) and considering first name to include a possible middle initial, middle name, etc.:
SELECT DISTINCT
[Full Name]
,REVERSE([Full Name]) -- to visualize what the formula is doing
,CHARINDEX(' ', REVERSE([Full Name])) -- finds the last space in the string
,[Last Name] = REVERSE(RTRIM(LTRIM(LEFT(REVERSE([Full Name]), CHARINDEX(' ', REVERSE([Full Name]))))))
,[First Name] = RTRIM(LTRIM(LEFT([Full Name], LEN([Full Name]) - CHARINDEX(' ', REVERSE([Full Name])))))
FROM ...
Note that this assumes [Full Name] has no spaces before or after the actual string. Otherwise, use RTRIM and LTRIM to remove these.
Let's suppose your table has Name column and it contains data like -
Random Person
FIRST LAST
Alpha Beta
The query will be like this
SELECT
LEFT(NAME,CHARINDEX(' ',NAME)) AS "First Name",
LTRIM(RTRIM(SUBSTRING(NAME,CHARINDEX(' ',NAME),100))) AS "Last Name"
FROM YOUR_TABLE