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
Related
http://sqlfiddle.com/#!9/027e1e/19
sample dataset here:
CREATE TABLE IF NOT EXISTS `test` (
`mode` varchar(10),
`value` int(3)
);
INSERT INTO `test` (`mode`, `value`) VALUES
('xx-a', '1'),
('xx-a', '1'),
('xx-c', '2'),
('xx-d', '3');
SQL query here:
SELECT CASE
WHEN mode LIKE '%-a' THEN 'a'
WHEN mode LIKE '%-b' THEN 'b'
ELSE 'c'
END AS channel,
IFNULL(SUM(value), 0)
FROM test
GROUP BY channel
When the value '%-b' does not exist in the database, it returns only 2 rows with 'a' and 'c'.
I need it to return 3 rows for all a, b, and c where b shows 0.
Thanks
A solution would be to use union all:
select
'a' channel,
sum(case when mode like '%-a' then value else 0 end) sum_value
from mytable
union all select
'b',
sum(case when mode like '%-b' then value else 0 end)
from mytable
union all select
'c',
sum(case when mode not like '%-a' and mode not like '%-b' then value else 0)
from mytable
Try this please
SELECT
CASE
WHEN mode LIKE '%-a' THEN 'a'
WHEN mode LIKE '%-b' THEN 'b'
ELSE 'c'
END AS channel,
IFNULL(SUM(value), 0),
IFNULL(COUNT(value), 0)
FROM database GROUP BY channel
UNION
SELECT 'b',0,0 FROM dual
WHERE not exists
(SELECT 1 FROM database WHERE mode LIKE '%-b')
I'm kind of new to MySQL but I've managed to find the individual solutions to two things I was trying to do, now I just need help combining them.
I have a database with a two tables: Users and user_profile. I have managed to create a query that combines data from both tables into a single table with the following:
select t1.id,
t1.name,
max(case when t2.`profile_key` = 'profile.address1' then t2.profile_value end) address,
max(case when t2.`profile_key` = 'profile.city' then t2.profile_value end) city,
max(case when t2.`profile_key` = 'profile.postal_code' then t2.profile_value end) postal_code,
max(case when t2.`profile_key` = 'profile.phone' then t2.profile_value end) phone
from users t1
left join user_profiles t2
on t1.id = t2.user_id
group by t1.id, t1.name
I would also like to split the "name" column into "first name" and "last name" so that I can sort by last name. I can accomplish that with this:
SELECT IF(
LOCATE(' ', `name`) > 0,
SUBSTRING(`name`, 1, LOCATE(' ', `name`) - 1),
`name`
) AS memberfirst,
IF(
LOCATE(' ', `name`) > 0,
SUBSTRING(`name`, LOCATE(' ', `name`) + 1),
NULL
) AS memberlast
FROM `users`;
Is there a way to combine these quires into one?
I think I understand that you want the first and last name instead of just the name, so try this:
SELECT t1.id,
IF(
LOCATE(' ', t1.name) > 0,
SUBSTRING(t1.name, 1, LOCATE(' ', t1.name) - 1),
t1.name
) AS memberfirst,
IF(
LOCATE(' ', t1.name) > 0,
SUBSTRING(t1.name, LOCATE(' ', t1.name) + 1),
NULL
) AS memberlast ,
MAX(CASE WHEN t2.`profile_key` = 'profile.address1' THEN t2.profile_value END) address,
MAX(CASE WHEN t2.`profile_key` = 'profile.city' THEN t2.profile_value END) city,
MAX(CASE WHEN t2.`profile_key` = 'profile.postal_code' THEN t2.profile_value END) postal_code,
MAX(CASE WHEN t2.`profile_key` = 'profile.phone' THEN t2.profile_value END) phone
FROM users t1
LEFT JOIN user_profiles t2
ON t1.id = t2.user_id
GROUP BY t1.id, t1.name
UNION SELECT, row1_name, row2_name, FROM tbl_name should do the trick, can't remember if syntax is correct but the query is union :)
I have a student table that has three columns
1. Student Name
2. Class Name
3. Test result
A student takes more than one tests with different results. I am trying to get the data into another table that has
1. Stundent Name+CLass Name ( Concatenated )
2. Pass (No of tests Passed)
3. Fail (No of tests failed)
4. Absent (No of tests Absent)
I use
select count(*)
from Student
where Result in ('Passed')
group by StuName, ClassName;
to get the count of passed subject for each stu+class combination. Similarly for failed and absent tests.
How should I modify the code to make an insert into the Table two??
MySQL supports inline IF statement,
SELECT CONCAT(StudentName, ' ', ClassName) Student_Class,
SUM(test = 'PASSED') totalPass,
SUM(test = 'Failed') totalFailed,
SUM(test = 'Absent') totalAbsent
FROM student
GROUP BY CONCAT(StudentName, ' ', ClassName)
and when you want to insert the result from the query above, use INSERT INTO..SELECT statement,
INSERT INTO tableNAME(col1, totalPass, totalFailed, totalAbsent)
SELECT CONCAT(StudentName, ' ', ClassName) Student_Class,
SUM(test = 'PASSED') totalPass,
SUM(test = 'Failed') totalFailed,
SUM(test = 'Absent') totalAbsent
FROM student
GROUP BY CONCAT(StudentName, ' ', ClassName)
You can easily pivot the data using an aggregate function with a CASE:
select concat(StuName, ',', ClassName) StuNameClass,
sum(case when result = 'Passed' then 1 else 0 end) Passed,
sum(case when result = 'Fail' then 1 else 0 end) Fail,
sum(case when result = 'Absent' then 1 else 0 end) Absent
from Student
group by concat(StuName, ',', ClassName);
Then if you want to insert the data into your other table:
insert into Table2 (StudentClassName, Passed, Fail, Absent)
select concat(StuName, ',', ClassName) StuNameClass,
sum(case when result = 'Passed' then 1 else 0 end) Passed,
sum(case when result = 'Fail' then 1 else 0 end) Fail,
sum(case when result = 'Absent' then 1 else 0 end) Absent
from Student
group by concat(StuName, ',', ClassName);
INSERT INTO t (name_class, passed_count, failed_count, absent_count)
SELECT CONCAT(StuName, ' ', ClassName) AS name_class,
SUM(IF(Result='Passed', 1, 0)) AS passed_count,
SUM(IF(Result='Failed', 1, 0)) AS failed_count,
SUM(IF(Result='Absent', 1, 0)) AS absent_count
FROM Student
GROUP BY StuName, ClassName;
I've read a lot of the examples on self join, but they don't seem to cover the case where some fields are not in some rows.
For eg, I have a database with:
testId, testItem, testResult
And the rows:
1,test1,1
1,test2,0
1,test3,1
2,test1,0
2,test4,1
2,test5,1
I would like the output:
testItem,a.testId,b.testId,a.testResult,b.testResult
test1,1,2,1,0
test2,1,NULL,0,NULL
test3,1,NULL,1,NULL
test4,NULL,2,NULL,1
test5,NULL,2,NULL,1
Essentially, I want to compare each testItem (test1->test5) from two different testIds (1 and 2) and compare their testResult values, factoring in testIds that may not have the same test Items.
Given your exact requirement, you can try this:
select testItem
, max(case when testID = 1 then testID else null end) as testID1
, max(case when testID = 2 then testID else null end) as testID2
, max(case when testID = 1 then testResult else null end) as testResult1
, max(case when testID = 2 then testResult else null end) as testResult2
from mytable
where testID in (1,2)
group by testItem
This makes a lot of assumptions about your data, so take it with a grain of salt.
It looks like you want a FULL OUTER JOIN, which is not supported in MySQL. You can emulate this with a UNION of two queries: a LEFT JOIN query and RIGHT JOIN which throws out matching rows.
Something like this will return the specified resultset:
SELECT a.testItem
, a.testId AS `a.testId`
, b.testId AS `b.testId`
, a.testResult AS `a.testResult`
, b.testResult AS `b.testResult`
FROM mytable a
LEFT
JOIN mytable b
ON b.testItem = a.testItem
AND b.testId = 2
WHERE a.testId = 1
AND a.testItem IN ('test1','test2','test3','test4','test5')
UNION ALL
SELECT d.testItem
, c.testId
, d.testId
, c.testResult
, d.testResult
FROM mytable d
LEFT
JOIN mytable c
ON c.testItem = d.testItem
AND c.testId = 1
WHERE d.testId = 2
AND d.testItem IN ('test1','test2','test3','test4','test5')
AND c.testId IS NULL
ORDER
BY 1,2,4
(I included the predicates on testItem IN ('test1' thru 'test5') because you specified that as a requirement; those predicates could be removed if you want all values for testItem included.)
SQLFiddle Demo
select testItem,
group_concat(IFNULL(testId,'null') separator ', ') testIds,
group_concat(IFNULL(testResult, 'null') separator ', ') testResults
from table_name group by testItem;
i need an example of nested if-else condition in mysql query
You could also use case statements for if-else conditions
SELECT
(CASE field1
WHEN 'A' THEN 'value is A'
WHEN 'B' THEN 'value is B'
ELSE 'value is neither A or B'
END)
FROM your_table;
or
SELECT
(CASE
WHEN (field1 IS NULL) THEN 'value is NULL'
WHEN (field1 = 1) THEN 'value is 1'
ELSE 'value is neither NULL or 1'
END)
FROM your_table;
You mean the IF(expr, expr, expr) function as defined here? An example would be:
SELECT
name, ID,
IF(category = 'fulltime', 1,
IF(category = 'parttime', loading, 0)) AS equivloading
FROM
person