How can we logically AND-connect two boolean columns in SQL in the select clause?
Pseudo-SQL of what I have in mind:
select boolean_col_A AND boolean_col_B as joint_bool from foo where id = 42
Note that I am not limiting the number of records through a boolean predicate but rather create a "synthetic" i.e. surrogate column in the result set.
I feel there must be a simple way to achieve this but I'm not seeing it. It should work for Oracle, Postgres and H2.
IMHO, use case might be a better option because Oracle is included, To the best of my knowledge Oracle can't have a boolean column so usually we just use a varchar(1) or char(1) with t/f
So instead of having boolean column, you can considerate just use string column with t/f across all database, then a simple case (like below) can work with all of them.
select case when colA = 't' and colB = 't' then 't' else 'f' end as joint_bool
from [TableName]
Thanks for all the feedback. My application uses Liquibase to abstract schema definitions. It maps the boolean type as follows:
H2: BOOLEAN
Postgres: BOOLEAN
Oracle: NUMBER(1)
Source: https://stackoverflow.com/a/28626825/131929
This is also the answer to #codeflush.dev's Q in the comments.
which datatype(s) do you use for each boolean in each RDBMS?
Given the list of effective RDBMS types above one way to go about this surrogate boolean column in the result set is to use BITAND. It is supported in the all database products relevant to this questions.
The more general CASE WHEN approach presented in the other answer is likely ok if you can't use BITAND.
select
(case when boolean_col_A =1 and boolean_col_B=1 then 'true'
else 'false'
end ) joint_bool
from foo where id = 42
try this.
Related
Someone gave me this code:
select * from table where is_active
Is the is_active column, despite not having been set to anything, set to TRUE by default? Does the above query mean this:
select * from table where is_active = TRUE
It appears so, but couldn't find anything in the PostgreSQL documentation, so just wanted to confirm.
Yes. You are right here. When the system looks at this query select * from table_name where col1>col2, it tries to find effective boolean expression after where clause, and ends up evaluating the expression to either true or false. But since the column value is already boolean so there is no need for that. select * from table where is_active is infact better. This is true for all SQL languages
I have the following column, B represents boolean and the rest are empty values. I have to change all the values in this column to the word COLUMN A.
COLUMN
-----
B
I have tried different things, for example
SELECT COLUMN
FROM TABLE
WHERE COALESCE(NULLIF(COLUMN,''), 'COLUMN A');
And I receive the error: "Invalid character found in a character string argument of the function "BOOLEAN"." I'm kind of stuck to this question and I'm getting confused with this boolean value. I will be really happy if someone can help me, thanks!
The easiest thing is to use CASE expression. I am not familiar in db2, so you may want to research it further, but in other DBMSs it works like this:
SELECT CASE
WHEN COLUMN = '' THEN 'COLUMN A' -- if COLUMN = '', replace it with 'COLUMN A'
ELSE COLUMN -- otherwise, keep COLUMN as is.
END as 'COLUMN' -- name the column in the result 'COLUMN'
FROM TABLE
This is an article that explains how it works in db2:
https://www.ibm.com/support/knowledgecenter/en/SSEPEK_11.0.0/sqlref/src/tpc/db2z_caseexpression.html
The WHERE clause is unfinished. Compare the COALESCEd value to something:
SELECT COLUMN
FROM TABLE
WHERE COALESCE(NULLIF(COLUMN,''), 'COLUMN A') = 'COLUMN A';
Or better:
SELECT COLUMN
FROM TABLE
WHERE COLUMN IS NULL OR COLUMN = ''
Doesn't require any thinking/calculating to work out your selection logic. More maintainable, nicer for peer developers
*The above is generic advice for usual cases NOT involving boolean datatypes (which typically require some different treatment)
Now, you say you have to change the value to something. That requires an UPDATE statement. If this column is a boolean then it won't have a value of empty string. The blanks will be nulls:
UPDATE TABLE SET COLUMN = (some boolean) WHERE COLUMN IS NULL
If you don't want to permanently change the table data to something, but instead want to select it out as some value where a blank occurs, but keep the blanks stored in the table:
SELECT COALESCE(column, (some boolean)) FROM TABLE
Might be worth noting that not all versions of DB2 can return a boolean in a result set - this is quite typical of database vendors. Convert the boolean to something else representable using a case when, if your DB2 version is thus restricted
SELECT CASE WHEN column = TRUE THEN 'true' ELSE 'false' END FROM TABLE
I would like to create a sql query (or plpgsql) that will md5() all given rows regardless of type. However, below, if one is null then the hash is null:
UPDATE thetable
SET hash = md5(accountid || accounttype || createdby || editedby);
I am later using the hash to compare uniqueness so null hash does not work for this use case.
The problem was the way it handles concatenating nulls. For example:
thedatabase=# SELECT accountid || accounttype || createdby || editedby
FROM thetable LIMIT 5;
1Type113225
<NULL>
2Type11751222
3Type10651010
4Type10651
I could use coalesce or CASE statements if I knew the type; however, I have many tables and I will not know the type ahead of time of every column.
There is much more elegant solution for this.
In Postgres, using table name in SELECT is permitted and it has type ROW. If you cast this to type TEXT, it gives all columns concatenated together in string that is actually JSON.
Having this, you can get md5 of all columns as follows:
SELECT md5(mytable::TEXT)
FROM mytable
If you want to only use some columns, use ROW constructor and cast it to TEXT:
SELECT md5(ROW(col1, col2, col3)::TEXT)
FROM mytable
Another nice property about this solution is that md5 will be different for NULL vs. empty string.
Obligatory SQLFiddle.
You can also use something else similar to mvp's solution. Instead of using ROW() function which is not supported by Amazon Redshift...
Invalid operation: ROW expression, implicit or explicit, is not supported in target list;
My proposition is to use NVL2 and CAST function to cast different type of columns to CHAR, as long as this type is compatible with all Redshift data types according to the documentation. Below there is an example of how to achieve null proof MD5 in Redshift.
SELECT md5(NVL2(col1,col1::char,''),
NVL2(col2,col2::char,''),
NVL2(col3,col3::char,''))
FROM mytable
This might work without casting second NVL2 function argument to char but it would definately fail if you'd try to get md5 from date column with null value.
I hope this would be helpful for someone.
Have you tried using CONCAT()? I just tried in my PG 9.1 install:
SELECT CONCAT('aaaa',1111,'bbbb'); => aaaa1111bbbb
SELECT CONCAT('aaaa',null,'bbbb'); => aaaabbbb
Therefore, you can try:
SELECT MD5(CONCAT(column1, column2, column3, column_n)) => md5_hash string here
select MD5(cast(p as text)) from fiscal_cfop as p
I'm using SQL Server 2005 with asp.net C#.
There is a search query on my site with different parameters.
fromAge as tinyint
toAge as tinyint
fromHeight as tinyint
toHeight as tinyint
gender as tinyint
withImage as bit
region as tinyint
astrologicaSign as tinyint
I get these parameters from first time use performs a search and save his search preferences in search table and then use them on Users table from which I select users that meet with requirements.
Problem is that some values can be conditional like for example withImage (bit) this means that now I need to have if statement that check whether I provided 0 or 1 to withImage and then perform select ie. if withImage=1 then query's where would be picture1<>'0' else without where condition at all.
I did end up with 10 nested if statements with initial query (which I simplified for example sake).
Is there way to avoid it except dynamic SQL?
This is quite simply achieved using an AND statement
SELECT * FROM User
WHERE (withImage =1 AND picture1<>'0') OR withImage=0
You can then add similar clauses for each element. Note that if the logic gets more complicated you can also use CASE statements in the WHERE clause.
If you can align the parameter values you are passing to be equal to the values you want to retreive (or at least always do an equals comparison) then you can use CASE WHEN quite efectively like this
SELECT * FROM User
WHERE picture1 = CASE WHEN #WithImage = 1 THEN #withImage ELSE picture1 END
That way it is comparing the picture1 field with the parameter if it is 1 or comparing the field with itself if it is not.
Others have given you a solution but honestl , this is one case where dynamic SQL is likely to improve performance. I'm not a big dynamic SQL fan, but this is one case where it does a better job than most anything else.
I have a table with 10 columns as col_1,col_2,.... col_10. I want to write a select statement that will select a value of one of the row and from one of these 10 columns. I have a variable that will decide which column to select from. Can such query be written where the column name is dynamically decided from a variable.
Yes, using a CASE statement:
SELECT CASE #MyVariable
WHEN 1 THEN [Col_1]
WHEN 2 THEN [Col_2]
...
WHEN 10 THEN [Col_10]
END
Whether this is a good idea is another question entirely. You should use better names than Col_1, Col_2, etc.
You could also use a string substitution method, as suggested by others. However, that is an option of last resort because it can open up your code to sql injection attacks.
Sounds like a bad, denormalized design to me.
I think a better one would have the table as parent, with rows that contain a foreign key to a separate child table that contains ten rows, one for each of those columns you have now. Let the parent table set the foreign key according to that magic value when the row is inserted or updated in the parent table.
If the child table is fairly static, this will work.
Since I don't have enough details, I can't give code. Instead, I'll explain.
Declare a string variable, something like:
declare #sql varchar(5000)
Set that variable to be the completed SQL string you want (as a string, and not actually querying... so you embed the row-name you want using string concatenation).
Then call: exec(#sql)
All set.
I assume you are running purely within Transact-SQL. What you'll need to do is dynamically create the SQL statement with your variable as the column name and use the EXECUTE command to run it. For example:
EXECUTE('select ' + #myColumn + ' from MyTable')
You can do it with a T-SQl CASE statement:
SELECT 'The result' =
CASE
WHEN choice = 1 THEN col1
WHEN choice = 2 THEN col2
...
END
FROM sometable
IMHO, Joel Coehoorn's case statement is probably the best idea
... but if you really have to use dynamic SQL, you can do it with sp_executeSQL()
I have no idea what platform you are using but you can use Dynamic LINQ pretty easily to do this.
var query = context.Table
.Where( t => t.Id == row_id )
.Select( "Col_" + column_id );
IEnumerator enumerator = query.GetEnumerator();
enumerator.MoveNext();
object columnValue = enumerator.Current;
Presumably, you'll know which actual type to cast this to depending on the column. The nice thing about this is you get the parameterized query for free, protecting you against SQL injection attacks.
This isn't something you should ever need to do if your database is correctly designed. I'd revisit the design of that element of the schema to remove the need to do this.