How can I limit columns returned based on their value? - sql

I have a table which looks like
index customer_number ABC CWD ROE BEE
1 1 0 0 0 1
and I want to return only the field names that have value 1 in this case 'BEE'
I found that by SHOW FIELDS I can get the names of the fields but how I can say show the field names where field value = 1?

I would use CASE statement here.
SELECT
index, customer_number,
CASE
WHEN abc=0 THEN 'abc'
WHEN cwd=0 THEN 'cwd'
END
FROM
table_name

You can't do this in a general way.
What you can do is write a sql statement like this:
select index, customer_number, decode (ABC, 1, "ABC", null) || decode (CWD, 1, "CWD", null) || decode (ROE, 1, "ROE", null) || decode (BEE, 1, "BEE", null) from aTable
It will display the column names for each entry where the value equals to one. It is oracle sql, so if you use a different rdbms the syntax will vary.

The beat it to death answer is to use CASE statements, one for each column. Something like:
SELECT CASE WHEN index=1 THEN "index" ELSE "no_index" END as i,
CASE WHEN customer=1 THEN "customer" ELSE "no_customer" END as c,
CASE WHEN ...

This is not something that SQL was really meant to do, and would be better done with application logic.
That said, if you really wanted to do it, you would probably need to involve a temp table and a SPROC:
Get the row and determine which fields are set.
Use that information to create a temp table with only the set fields.
Insert the data into that temp table, then select the rows from there.
It would be a huge mess of SQL to replace what would amount to only a few lines of application code. Probably not worth it.

Related

SELECT * from a table but add conditional to one column?

Is it possible in PostgreSQL to SELECT * from a table, but add a condition to one column in that result and overwrite it? I'll explain easier with a code example of what I'm trying to do (pseudo code)
SELECT
*,
CASE
WHEN column_name=1 THEN 'one'
WHEN column_name=2 THEN 'two'
ELSE 'other'
END AS column_name
FROM table
and this returns something like:
id | name | column_name | created_at
------------------------------------
1 | Title | one | 123456789
So basically, I want to get every column without having to type each column out, but specifically alter the value of one column in the result based on some condition.
=== UPDATE ======
A little more clarification on what I am doing.
I'm writing a plpgsql function that returns a type of, for the above example RETURNS schema.table. This is then (via Postgraphile) accessed through a GraphQL endpoint and returned to our app, that is all typed with TypeScript using codegen.
So in essence, the column name needs to be 1. the same name and 2. not an alias name, as Postgraphile/GraphQL won't know this value so will be omitted.
=== UPDATE 2 ======
Ok I have done it now, but a different way. I looked at it and realised there is a easier way for me to do this, and why I never did it in the first place I don't know. I won't mark this resolved though, as my answer doesn't answer this question.
To get around this, I simply return my resultset into a varaible and alter this before returning:
SELECT schema.table.* INTO cached_data
...
IF cached_data.column_name = 'something' THEN
cached_data.column_name = 'something-else';
END IF;
RETURN cached_data;
This works perfectly for my situation.
If you have to use *, specify the table (alias if necessary)
SELECT
t1.*,
CASE
WHEN column_name=1 THEN 'one'
WHEN column_name=2 THEN 'two'
ELSE 'other'
END AS column_name
FROM table t1
This will return all columns from table, plus the new column. If you want to replace that column from table, explicitly state all required columns.
Note: If column_name is already a column in the table, then you will get two columns in the result set with the same name using this approach (HT #Milney)
You can give a nickname to your table and use TABLE_ NICKNAME.* as follow:
SELECT t.*,
CASE id
WHEN 1 THEN 'one'
WHEN 2 THEN 'two'
ELSE 'other'
END AS column_name
FROM your_table t

Compare comma separated list with individual row in table

I have to compare comma separated values with a column in the table and find out which values are not in database. [kind of master data validation]. Please have a look at the sample data below:
table data in database:
id name
1 abc
2 def
3 ghi
SQL part :
Here i am getting comma separated list like ('abc','def','ghi','xyz').
now xyz is invalid value, so i want to take that value and return it as output saying "invalid value".
It is possible if i split those value, take it in temp table, loop through each value and compare one by one.
but is there any other optimal way to do this ??
I'm sure if I got the question right, however, I would personally be trying to get to something like this:
SELECT
D.id,
CASE
WHEN B.Name IS NULL THEN D.name
ELSE "invalid value"
END
FROM
data AS D
INNER JOIN badNames B ON b.Name = d.Name
--as SQL is case insensitive, equal sign should work
There is one table with bad names or invalid values if You prefer. This can a temporary table as well - depending on usage (a black-listed words should be a table, ad hoc invalid values provided by a service should be temp table, etc.).
NOTE: The select above can be nested in a view, so the data remain as they were, yet you gain the correctness information. Otherwise I would create a cursor inside a function that would go through the select like the one above and alter the original data, if that is the goal...
It sounds like you just need a NOT EXISTS / LEFT JOIN, as in:
SELECT tmp.InvalidValue
FROM dbo.HopeThisIsNotAWhileBasedSplit(#CSVlist) tmp
WHERE NOT EXISTS (
SELECT *
FROM dbo.Table tbl
WHERE tbl.Field = tmp.InvalidValue
);
Of course, depending on the size of the CSV list coming in, the number of rows in the table you are checking, and the style of splitter you are using, it might be better to dump the CSV to a temp table first (as you mentioned doing in the question).
Try following query:
SELECT SplitedValues.name,
CASE WHEN YourTable.Id IS NULL THEN 'invalid value' ELSE NULL END AS Result
FROM SplitedValues
LEFT JOIN yourTable ON SplitedValues.name = YourTable.name

Replace value in result by a specific value

I need to make a query to collect some data from a database via SQL. In this data there is 1 value used as collection value. This are ID's of courses given. Sometimes a course can be given about f.e. Office. But people can do a course there for word, excel, powerpoint... But this is all given in 1 course by 1 tutor. Still for statistics I need to know if they participated the course for Word, Excel, Powerpoint ...
Is it possible to replace values in the resultset? With this i mean something like this:
if value = courseValue ==> replace value with specific courseValue (I can get the value via a subquery)
I hope this makes my problem clear and i appriciate all the help!
You can use a case statement in your select to return something other than the course id that is on the row. For example:
SELECT
field1 AS 'Name',
CASE
WHEN field2 = 'Foo'
THEN 'Bar'
WHEN field2 = 'Lorem'
THEN 'Ipsum'
ELSE 'Some Value'
END
AS 'Type',
field3 AS 'Description'
FROM table
If I understand you correctly, you will need something along the lines of this:
Create a new table with "courseID" and "replacementID" columns, fill it for the cases where there is a replacement
In your query do an outer join with this table over the courseID fields and also return the "replacementID", which can be null is there is no replacement
Use either the replacementID if it isn't null or the courseID

TSQL - ISNULL over multiple columns

I have a simple SQL query (SQL Server 2005) where I'm selecting from a table that contains multiple columns that have BIT values.
These columns are nullable so can contain NULL, 0 or 1.
There are a fair number of these columns and in my query I want to return zero if the value is NULL.
I'm currently using ISNULL like so:
SELECT Name, Age, ISNULL(LikesOranges,0), ISNULL(LikesApples,0), ISNULL(LikesPears,0)
FROM FoodPreferences
As I've mentioned, there are a lot of these BIT columns (much more than in the simple example above).
Is there a way I can use ISNULL over multiple columns like this:
SELECT ISNULL(*,0) FROM FoodPreferences
The above query doesn't work but you get what I'm trying to do - so I can avoid having to write an ISNULL statement for each column,
Thanks.
Try this:
SELECT COALESCE(LikesOranges, LikesApples, LikesPears) AS MyBit FROM FoodPreferences
This will return the first non-null value. If all fields are NULL the result is NULL.
UPDATE:
And the conclusion is:
SELECT ISNULL(COALESCE(LikesOranges, LikesApples, LikesPears),0) AS MyBit FROM FoodPreferences
so I can avoid having to write an
ISNULL statement for each column,
Run this query and copy the result to your select statement. system_type_id = 104 filters the result on bit columns.
select stuff((select ', isnull('+name+', 0)'
from sys.columns
where object_id = object_id('FoodPreferences') and
system_type_id = 104
for xml path('')), 1, 1, '')
Result:
-------------------------------------------------------------------------
isnull(LikesOranges, 0), isnull(LikesApples, 0), isnull(LikesPears, 0)
I don't think so. But an option might be to create a view onto that table and put all the ISNULL statements in the view. At least then you won't have to do it every time
eg.
CREATE VIEW vwFoodPreferences
AS
SELECT Name,
Age,
ISNULL(LikesOranges,0) AS LikesOranges,
ISNULL(LikesApples,0) AS LikesApples,
ISNULL(LikesPears,0) AS LikesPears
FROM FoodPreferences
Unfortunately, the simple answer is no.
You could write sql dynamically, but whatever happens, the final resulting sql would have to be ISNULL(a,0), ISNULL(b,0), ISNULL(c,0), ISNULL(d,0), etc
i think you can write a simple program and generate select clause by reading all columns and generating the select
while not this :
SELECT COALESCE(LikesOranges, LikesApples, LikesPears, 0) AS MyBit FROM FoodPreferences
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/coalesce-transact-sql?view=sql-server-2017

Check whether a table contains rows or not sql server 2005

How to Check whether a table contains rows or not sql server 2005?
For what purpose?
Quickest for an IF would be IF EXISTS (SELECT * FROM Table)...
For a result set, SELECT TOP 1 1 FROM Table returns either zero or one rows
For exactly one row with a count (0 or non-zero), SELECT COUNT(*) FROM Table
Also, you can use exists
select case when exists (select 1 from table)
then 'contains rows'
else 'doesnt contain rows'
end
or to check if there are child rows for a particular record :
select * from Table t1
where exists(
select 1 from ChildTable t2
where t1.id = t2.parentid)
or in a procedure
if exists(select 1 from table)
begin
-- do stuff
end
Like Other said you can use something like that:
IF NOT EXISTS (SELECT 1 FROM Table)
BEGIN
--Do Something
END
ELSE
BEGIN
--Do Another Thing
END
FOR the best performance, use specific column name instead of * - for example:
SELECT TOP 1 <columnName>
FROM <tableName>
This is optimal because, instead of returning the whole list of columns, it is returning just one. That can save some time.
Also, returning just first row if there are any values, makes it even faster. Actually you got just one value as the result - if there are any rows, or no value if there is no rows.
If you use the table in distributed manner, which is most probably the case, than transporting just one value from the server to the client is much faster.
You also should choose wisely among all the columns to get data from a column which can take as less resource as possible.
Can't you just count the rows using select count(*) from table (or an indexed column instead of * if speed is important)?
If not then maybe this article can point you in the right direction.
Fast:
SELECT TOP (1) CASE
WHEN **NOT_NULL_COLUMN** IS NULL
THEN 'empty table'
ELSE 'not empty table'
END AS info
FROM **TABLE_NAME**