I am (new to) working in MySQL but so far I was getting along OK. Now I'm stuck on the following:
I want to show a column in the query result but only if a certain condition is met. If the condition is not met then I would like the column not to show up in the query result (rather than show an empty column with only NULL values).
I tried to use a CASE WHEN statement but in that case it always shows the column in the query result, even if it is empty.
The problem is that I need to do this for 12 columns. The main reason is to avoid the query result to be cluttered with useless empty columns. The result of the query is to be processed by other people in excel.
Thanks in advance for your kind replies.
Although not ideal, you could use a prepared statement to only select columns where some rows are not null.
Suppose you have this table test where c is null for all the rows:
a
b
c
1
1
null
2
null
null
null
3
null
You can do this:
SET #query = 'SELECT ';
SET #query = CASE WHEN (SELECT COUNT(a) FROM test) > 0 then CONCAT(#query, 'a,') ELSE #query END;
SET #query = CASE WHEN (SELECT COUNT(b) FROM test) > 0 then CONCAT(#query, 'b,') ELSE #query END;
SET #query = CASE WHEN (SELECT COUNT(c) FROM test) > 0 then CONCAT(#query, 'c,') ELSE #query END;
SET #query = CONCAT(TRIM(TRAILING ',' FROM #query), ' FROM test');
Then:
PREPARE statement FROM #query;
EXECUTE statement;
Output:
a
b
1
1
2
null
null
3
Fiddle
Related
i have a table like this
A B C
1 4 7
2 5 8
3 6 9
And i want result like this
Columns Values
A sum(A) = 6
B sum(B) = 15
C sum(C) = 24
Its simple in Excel sheets but im stuck in MySql
Appreciate the help
Thanks
-- SeasonType,Sacks,SacksYards are columns
select SeasonType,
MAX(IF(SeasonType = '1', Sacks, null)) AS 'Q1',
MAX (IF(SeasonType = '1', SacksYards, null)) AS 'Q2'
from t3 GROUP BY SeasonType
-- union all attempt column sacks,sacksyards table --
-- fantasydefencegame
select 'Sacks' as Sacks, 'SackYards' as SackYards, 0 as SortOrder
union all
select Sum(Sacks) total from fantasydefensegame
union
select Sum(SackYards) from fantasydefensegame
union
select sum(PointsAllowed) from fantasydefensegame
group by SeasonType
select sum(Sacks) sacks from t3
union all
select sum(SackYards) sackyards from t3 group by SeasonType
**-- Another rough Attempt on Temp table**
Select sum(Sacks),sum(Sackyards) from t5
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(case when Season = '2009' ''',
Season,
''' then field_value end) ',
Season
)
) INTO #sql
FROM
t5;
SET #sql = CONCAT('SELECT Sacks, ', #sql, '
FROM t5
GROUP BY Season');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
This should fairly give you some ideas. Supposing we are using a test database named testdb and your original table is named test which has 3 columns i.e a,b,c . The three rows in the table are just like what you provided before. Next we can proceed to create a stored procedure. Note: The reason behind using a prepared statement to get the sum value for each column is due to the rules that column names have to be hardcoded , which can not be replaced with variables. e.g select sum(a) from test; can not be written as select sum(#column_name) from test;. By using a prepared statement, we can hardcode the column name dynamically.
delimiter //
drop procedure if exists table_sum//
create procedure table_sum (db_name varchar(20),tb_name varchar(20))
begin
declare col_name varchar(10);
declare fin bool default false;
declare c cursor for select column_name from information_schema.columns where table_schema=db_name and table_name=tb_name;
declare continue handler for not found set fin=true;
drop temporary table if exists result_tb;
create temporary table result_tb (`Columns` varchar(10),`Values` varchar(25));
open c;
lp:loop
fetch c into col_name;
if fin=true then
leave lp;
end if;
set #stmt=concat('select sum(',col_name,') into #sum from test ;');
prepare stmt from #stmt;
execute stmt;
deallocate prepare stmt;
set #val=concat('sum(',col_name,') = ',#sum);
insert result_tb values(col_name,#val);
end loop lp;
close c;
select * from result_tb;
end//
delimiter ;
Finally we call the procedure to get the desired output:
call table_sum('testdb','test');
I would avoid prepared statements and dynamic sql unless I really need it. And I would use such powerful tool when I need to generalize on a value that increases, on a large set of columns.
In your specific case of the shared columns, you could use a simple approach that does the union of the three columns with their respective sum.
SELECT 'A' AS `Columns`,
SUM(A) AS `Values`
FROM tab
UNION
SELECT 'B' AS `Columns`,
SUM(B) AS `Values`
FROM tab
UNION
SELECT 'C' AS `Columns`,
SUM(C) AS `Values`
FROM tab
Check the demo here.
i've got a query that works perfectly on a table, and doesn't work on another:
Here's the code (please note that is part of another query):
SET #sql = Null;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT('SUM(CASE WHEN columnA = "' ,columnA, ' "THEN 1 ELSE 0 end) AS "' ,columnA, ' "'))
into #sql
from table;
I don't know why it works for a table, but when i switch on another table it gives me this error
1 row(s) affected, 1 warning(s): 1260 Row 12 was cut by GROUP_CONCAT()
IF i remove the #sql thing and i do the select it gives me the data without error...BUT it truncates the string at some point... i don't know why
Cause you are trying to build a dynamic query (prepared statement) which should be something like below. Again you CASE condition CASE WHEN columnA = columnA THEN 1 ELSE 0 end doesn't seems valid since columnA = columnA will always be true.
declare #sql varchar(200);
set #sql = 'SELECT
GROUP_CONCAT(DISTINCT
CONCAT(SUM(CASE WHEN columnA = columnA THEN 1 ELSE 0 end) AS columnA))
into (another sql query part)
from table';
group_concat() has a maximum length, and you seem to be exceeding that. This is documented here.
You can reset the maximum length.
But, you can also simplify your logic:
SET #sql = Null;
SELECT GROUP_CONCAT(DISTINCT REPLACE('SUM(ColumnA = ''#val'') as `#val`',
'#val', columnA))
into #sql
from table;
Without the case expression, perhaps your string will fit in the default length.
I find it much easier to use replace() for constructing strings rather than concat(). You can see the template that you are using.
following is a part of my stored proceedure im using it to extract data from my db.
query
BEGIN
SET #sqlstring = CONCAT("SELECT b.ID, c.name, c.accountID,, b.total_logs, a.time_start, a.time_end ,COUNT(a.id) AS number_of_users
FROM ",logtable," a INNER JOIN users b on a.ID = b.ID INNER JOIN accounts c on b.accountID = c.accountID
GROUP BY ID;");
PREPARE stmt FROM #sqlstring;
EXECUTE stmt;
END
At times in the db, the logtable(table is passed in a variable like logtable_1, logtable_2 .... ) can be non existent, currently when the perticuler table is missing it crashes and throws an error because a.time_start, a.time_end cannot have values without the log table.
but what i want is just to assign NULL on values a.time_start, a.time_end without throwing an error,
So can any body tell is there a way i could modify this code like
BEGIN
if logtable exists
\\ the query
else
\\ the query
END
Find existence of the table by querying information_schema.tables. If it returns a count equals to 1 then you can proceed executing your query on the table. Otherwise go with your Else block.
Sample:
declare table_exists int default 0;
select count(1) into table_exists
from information_schema.tables
where table_schema='your_table_schema_name'
and table_name = 'your_table_name';
if table_exists then
-- do something
else
-- do something else
end if;
I have a Sql SP that applies filter based on parms being passed to the SP.
it works if i just pass valid values like (2,4) in example below.
but if no filter is passed it should return all rows. Problem is checking for
parmIndustryId is null or for parmIndustryId is '' empty string, without that it works but i need to be able to check for empty string or null.
this is the error i get
Error Code: 1241. Operand should contain 1
column(s) 0.000 sec
CREATE PROCEDURE `SearchIndustry`(
IN parmIndustryId TEXT
)
BEGIN
SET parmIndustryId ='2,4';
set #sql = CONCAT(' Select t1.*
FROM Industry t1
WHERE Active =1 AND(', parmIndustryId ,' is null OR t2.IndustryId IN( ', parmIndustryId, ' ))')
;
PREPARE q FROM #sql;
execute q;
END$$
DELIMITER ;
How Can i correctly pass value for IN operand filter?
You can use FIND_IN_SET():
SELECT *
FROM Industry
WHERE Active = 1
AND (parmIndustryId IS NULL OR FIND_IN_SET(IndustryId, parmIndustryId))
Edit, you may need to also use COALESCE if empty strings can be passed. If so, this will work:
SELECT *
FROM Industry
WHERE Active = 1
AND (COALESCE($parmIndustryId,'') = ''
OR FIND_IN_SET(IndustryId, $parmIndustryId));
SQL Fiddle Demo
How can I create an SQL select query to return variable as true(1) if a column value exists in a table else false(0).
I want to use this variable in my scripts so that
if variable=1
execute A
ELSE
execute B
In Oracle you can use something like this
SELECT
CASE nvl(length(column1), 0)
WHEN 0 THEN 0
ELSE 1
END AS column1
FROM yourTableName;
You can try this...
IF ((SELECT COUNT(*) FROM TableName WHERE FieldName = 'Whatever') <> 0)
-- Execute something if column value exists
ELSE
-- Execute something if column value does not exist
SELECT CASE WHEN EXISTS(SELECT 1 FROM tableName WHERE fieldName='value') THEN 1;
ELSE 0;
END
INTO variable
--that is PostgreSQL