I need to write a query which will look at a table, and select from it any/all columns(s) that have ALL NULL rows.
I would prefer to not have to say "SELECT (each column name)", but would rather say "SELECT (from whole table, those columns) WHERE (rows are all NULL).
I know about CASE and WHEN statements, but my understanding is that columns must be specifically referenced in the select statement. I'll be using this query on many different tables, with many different dimensions and column names, so I would like the query to be versatile.
I'm using SQL in Toad with a Vertica db.
This is what my tables look similar to:
This table contains the columns i need the query. The columns i need to query are such as "owner_id", NOT TYPE_NAME, NULLABLE, etc. Each row in THIS table, is actually a column with such and such many values, and it is these values I need to run my query against.
'Simply' put: If a column has ALL NULL rows, I need to identify and/or select it.
Any Suggestions? %Solved^^^%
I found this example of a way to loop through columns, but despite my research, I'm still having trouble making sense of it all.
Such as: how is col_names difference from column_name? Same for the text in the FROM statement and WHERE. Should those not both the table name? Then what does the found_rows() signify?
DECLARE col_names CURSOR FOR
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'tbl_name'
ORDER BY ordinal_position;
select FOUND_ROWS() into num_rows;
SET i = 1;
the_loop: LOOP
IF i > num_rows THEN
CLOSE col_names;
LEAVE the_loop;
END IF;
FETCH col_names
INTO col_name;
//do stuff
SET i = i + 1;
END LOOP the_loop;
As I understand you want to Identify which columns have NULL values on all rows and dont want to type all columns, right?
If thats so, this is how I would do:
1) Build a function that takes the as an input parameter and does:
--FYI: this is a pseudo code. I dont have mysql here to get the correct syntax
select sum(
case when CAST(<column_name> as varchar(5200)) is not null then 1 else 0 end --5200 seems to be your longer column
)
from YOUR_TABLE
--the idea is to cast the column as anythig; if it is null, it gets a 0.
--If the sum across the rows is 0, it means that all the rows are null
2) Loop through the column names and call the function
Related
This may seem like a repeat question, but it always seems to be questions involving more than one table. When a row in a table is selected, I will also need to +1 the view count in the same row. I know I can't use a trigger or two statements in the same query, but could both of these things be done with a single connection to the database? What would the preferred method be to both select a row and then +1 the view field?
It can be done in the same connection, but I can't think of a way for that to be done using one query.
Here is how you would do that in a single transaction;
START TRANSACTION;
UPDATE tbl SET view=view+1 WHERE id = 10;
SELECT * FROM tbl WHERE id = 10;
COMMIT;
A second "better" method you can do that which eliminates having to read the tbl table twice.
UPDATE tbl
SET view = (#viewsCount := view + 1)
WHERE id = 10;
And to get the new value of the views count I would do something like this
SELECT #viewsCount;
A third way would be by utilizing the LAST_INSERT_ID() function like so
UPDATE tbl
SET view = LAST_INSERT_ID(view) + 1
WHERE id = 10;
Then to get the new view count you will need to execute this query immediately after the update. you can not execute any other queries after the update otherwise you will not get the intended value.
SELECT LAST_INSERT_ID();
I have declared the variables (total,order_num,order_stts,id_cust,reMarks). But it have error that said result consisted of more than one row. How can i fix this error? Please help me fix this error, i'm new to sql.
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'.
#drop procedure if exists usp_GetAnything;
delimiter //
create procedure usp_GetAnything()
begin
declare total int default 0;
declare order_num varchar(45) default 000;
declare order_stts varchar(45) default 000;
declare id_cust int default 0;
declare reMarks varchar (45) default 000;
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
into order_num,order_stts,id_cust,total,reMarks
from customer c, order_status o
where c.c_id=o.c_id;
if (total > 0) then
update order_status o
set reMarks = 'UNAVAILABLE'
where order_num > '123';
else
select order_num,order_stts,total,reMarks
from order_status
where order_stts = 'waiting';
end if;
end
The error is due to the INTO clause in the second SELECT statement. That wouldn't be an error if the SELECT returned no more than one row.
But if that SELECT returns more than one row, MySQL will throw 1172 error. (You can test this by adding a "LIMIT 1" clause on that "SELECT ... INTO" statement, and verifying that the error is not thrown.
The procedure runs a SELECT to return a resultset, then issues an UPDATE statement to modify zero or more rows in a table.
The next part of the procedure is confusing; it's not clear what we are trying to achieve. The SELECT can return zero, one or more rows. If the intent is to perform a conditional test to determine whether there are any rows with item_total > 0,
Then one possible "fix" (to avoid the 1172 error) would be to add
AND o.item_total > 0 LIMIT 1
to the "SELECT ... INTO" statement.
Without an "ORDER BY", it's indeterminate which row would be returned. But it doesn't really look like it matters. Apart from the comparison of the returned o.item_total value, it doesn't look like the procedure is doing anything else with the columns returned.
The following UPDATE statement is only going to be executed if an item_total>0 row was found.
And the UPDATE statement will update all rows that have an order_number greater than a specified constant.
There doesn't appear to be any relationship to the row(s) returned by the previous SELECT ... INTO statement.
If the intent is to update the rows in order_status (that are related to a customer) if "any" row returned by the previous query has an item_total > 0, then the proposed "fix" would accomplish that.
The procedure then (conditionally) returns a second resultset (all rows from order_status with `order_stts = 'waiting'), but only if there wasn't any order_status row with and item_total>0.
We can fix the 1172 error, but this procedure has much bigger problems than that error. The whole procedure seems like bizarre approach to solving whatever problem it's supposed to be solving. It just looks like a jumble of SQL statements kludged together without a clear design.
This means
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;
the query above return multiple rows which is not acceptible if you are trying to store the result in a variable. So if you dont expect multiple rows, check your data, or if you are OK with the first row values, add limit 1 in the query
select o.order_no,o.o_status,c.c_id,o.item_total,o.remarks
into order_num,order_stts,id_cust,total,reMarks
from customer c, order_status o
where c.c_id=o.c_id limit 1;
You may try searching for Result consisted more than one row in Stackoverflow and you should be getting plenty of answers!!!
I am trying to create an sql trigger statement using phpmyadmin trigger interface.
Trying to do something for table 1 as shown below :
BEGIN
declare #valid_number int ;
select id into #valid_number from table 2 ;
if 10 does not exist in #valid_number then
{do something here}
end if;
END
how to achieve it?
First: a variable in a stored routine can't store multiple values, just a single one. Your statement
select id into #valid_number from table 2 ;
will only work, if the query returns exactly one row. An error will occur, if the query returns multiple rows, a warning, if the query returns no row at all, see the manual page to SELECT ... INTO:
The INTO clause can name a list of one or more variables, which can be
user-defined variables, stored procedure or function parameters, or
stored program local variables. [...]
The selected values are assigned to the variables. The number of
variables must match the number of columns. The query should return a
single row. If the query returns no rows, a warning with error code
1329 occurs (No data), and the variable values remain unchanged. If
the query returns multiple rows, error 1172 occurs (Result consisted
of more than one row).
Solution:
It's not difficult to create a statement that gives you the desired answer in exact one row, i.e.
SELECT COUNT(*) into valid_number FROM example WHERE id = 10;
This query will return 0, if the id 10 does not exists in column id and the count of occurences else. Of course there are several ways to achieve this, this is just one of them. You could rewrite your stored routine to:
BEGIN
-- prefer local variables, don't use user defined, if not needed.
DECLARE valid_number int;
SELECT COUNT(*) into valid_number FROM example WHERE id = 10;
IF valid_number = 0 THEN
-- do something here
END IF;
SELECT result;
END
Note
You could use a cursor to traverse the result of a query, but most times one wants to avoid a cursor. To use a cursor under similar conditions as of this question would not be the SQL way to do it and most times very inefficient.
I just set an SQL Stored Procedure to return a specific row in a specific order (from more to less important):
-- 1st Level -> Query a more detailed object...
SELECT ... WHERE something
-- if a result is find, the SP is returning the correct row.
-- if rowcount = 0 then, the SP is returning an empty row
-- and continues with the next query (less specific than the 1st one).
IF ##ROWCOUNT = 0
BEGIN
SELECT .... WHERE something else...
-- Again, if a result exists, the SP returns the correct row, but also
-- the result of the 1st query is returned without rows...
IF ##ROWCOUNT = 0
BEGIN
SELECT .... WHERE something else again...
END
END
Is there any option to only return the SELECT statement that returns a non empty row? I don't want to return empty rows... and each time the row is an "sub-level" of the 1st query, I get empty results before the correct row.
I was thinking to create a table variable. Are there any better ways?
Since you are looking for the lack of rows why not use an if/else statement in your procedure. Something like:
If exists(/*firstQuery*/ SELECT ... WHERE something) begin
SELECT ... WHERE something
end else if exists (/*secondQuery*/ SELECT .... WHERE something else... ) begin
SELECT .... WHERE something else...
end else /*Third query*/ begin
SELECT .... WHERE something else again...
end
Just remember when checking is something exists you should select only one column (for example the id) as if you have calculated columns then this can slow down your procedure.
hIs there any way to update all the columns of a mysql table for a particular record in one go to a particular value.
For e.g. I have a table that has around 70 columns , and they are by default set to 0 at the time of creating the table,when I add a new record via PHPmyadmin by just filling in one or two values and submitting it all the other fields are set to 0 , but I want to set all the fields to 1
many times ,so I need to set all the columns to 1 individually via PHPmyadmin
To speed-en up the process and
I tried
UPDATE tablename SET * = '1' WHERE id = '2' , but it does not work.
If anyone can provide a solution on similar lines , it would be great.
EDIT:
Is there a way without specifying all the 70 columns in the SQL statement? that what I am looking for. I do know how to update normally specifying columns in the SQL statement. Thank you.
If you are looking for a way to update all 70 columns to a single value with a short, simple statement, then I recommend that you write a stored procedure to do the update. That way you only need to write out the full update syntax once, and can re-use it over and over by calling the stored procedure.
CREATE PROCEDURE update_all_columns (p_new_value SMALLINT, p_id INT) ...
CALL update_all_columns(1,2);
Another trick is to use the information_schema.columns table to generate the update statement, making it less tedious to code the stored procedure.
Something like this:
SELECT concat('UPDATE ',
table_name,
' SET ',
group_concat(column_name separator ' = p_new_value, '),
' = p_new_value',
' WHERE id = p_id;') as sql_stmt
FROM information_schema.columns
WHERE table_schema = 'your_schema'
AND table_name = 'tablename'
AND column_name != 'id'
You have to name each column in an update statement.