Replace value in result by a specific value - sql

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

Related

SQL Query to get all the data from tables when there is no parameter

I am trying to get the whole data when there are no filters selected. I have made an array that contains the selections. In case there are no selections then there will be just '' , i.e. no characters but not null.
SELECT * FROM Skills WHERE person IN ('Technology', 'Drilling');
For example - In this query it will return all required - filtered data. So my array contains Technology and Drilling. In case there is nothing selected by the user as a filter then the query would look like:
SELECT * FROM Skills WHERE person IN ('');
In this case the table is returning nothing in SQL Server. I want it to return everything from the table without any filters.
I would really like to get some help here and maybe some resources that might help me achieve the required thing.
The array is being filled in javascript.
It seems really strange to have a column called person compared to values like "Drilling". But you would do something like:
SELECT *
FROM Skills
WHERE person IN (<whatever>) OR <whatever> = '';
Often NULL is used to mean everything, so that would be:
WHERE person IN (<whatever>) OR <whatever> IS NULL;
And "whatever" might be a delimited string, so this might look like:
WHERE person IN (SELECT s.value FROM string_split(#params) s) OR
#params IS NULL;

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

How to make a new column in SELECT clause and fill it with a string/list dynamically with concat of all condition statements satisfied?

So there are two tables in a database. I have to find out whichever rows have discrepancy based on certain conditions (in couple of cases that's just equality checking between fields). I report ID of those rows.
The problem is to also include the reasons in another column as to why that ID is reported. Because an id can be fail multiple conditions (like mismatch on two fields), I just wanted to include all of those reasons in another column.
Basic idea is to append all the mismatches in another column.
I've looked at several SO questions but they don't exactly my use case. So now I'm thinking it's not possible with SQL.
I searched Google for "enter dynamic column values based on conditions sql", and hit : SQL Conditional column data return in a select statement : This adds a static column
I also learned it's possible to add another column in SELECT with dynamic content like this:
SELECT id, CASE
WHEN columnname "DEF" then "I" ELSE "YOU" newColumnName
FROM tableName
But I have not been able to find dynamic column value assignment and update SQL. That's the problem.
Expected results:
I just want to be able to concat all the cases "strings" which a record is applicable for.
Do this with the two tables.
So because I have two tables to work with I have to put these conditions in the WHERE sub-clause, and not in the SELECT one.
So, if for ID = 345, column "FOO_MAN" does not match between two tables, and column "BAR_TOO" also does not match between two tables, then?
Then I want my select clause to capture information like this:
ID | REASON
345 | FOO_MAN BAR_TWO
It's probably easier to build this type of query dynamically (e.g. using a stored procedure) based on the conditions you want to test, but here is a small example which shows how it can be done:
SELECT t1.id,
CONCAT_WS(' ',
CASE WHEN t1.foo != t2.foo THEN 'foo' END,
CASE WHEN t1.bar != t2.bar THEN 'bar' END
) AS reason
FROM t1
JOIN t2 ON t2.id = t1.id
WHERE t1.foo != t2.foo OR t1.bar != t2.bar
Output (for my demo on dbfiddle)
id reason
2 foo
4 bar
5 foo bar

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

How can I limit columns returned based on their value?

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.