TSQL True/False IF ELSE Statement with CONTAINS - tsql

I'm trying to get a result of True or False by looking to see if my table contains a particular month and that meets some additional parameters.
SELECT:
SELECT DISTINCT Semester FROM Courses
WHERE Language = 'English'
AND Post = 1
AND Year = YEAR(getdate())
Which returns data like:
Semester
-------
November
October
I'd like to use CASE or IF/ELSE to determine if October exists in that select statement.
Something along the lines of:
IF (SELECT DISTINCT Semester FROM Courses
WHERE Language = 'English'
AND Post = 1
AND Year = YEAR(getdate())
CONTAINS(Semester, 'October')
THEN 'True'
ELSE 'False'
END IF
Which should give me True or False respectively.

I'd suggest doing something like this:
SELECT CASE WHEN EXISTS (SELECT *
FROM Courses
WHERE language = 'English'
AND Semester = 'October')
THEN 'True'
ELSE 'False' END As Result
That should give you what you want and keep quick performance on large tables

Related

Calculate column value based on another column that is calculated

I need to show the last date enrolled based on value that is derived in the Enrolled column. On this line below WHEN EnrolledDer = 'N' then LAST_DTE_OF_ATTEND. EnrolledDer doesn't exist because it is a derived column. It looks like I have to repeat the case statement to get EnrolledDer for the column to show LAST_DTE_OF_ATTEND for which the alias will be LastDateEnrolledDer. What is the syntax to nest that case statement and is that the best method?
If I try to reference the alias column in the case statement the error is Invalid Column named EnrolledDer'
CASE
WHEN EnrolledDer = 'N' then LAST_DTE_OF_ATTEND --'Invalid Column named EnrolledDer'
Sql Server 2014
SELECT [Student ID],
[Unique Course Identifier],
[Course Title],
Term,
[Section Number],
Days,
[Start Time],
[End Time],
[Start Date],
[End Date],
Enrolled,
--Case, If C then Y, else N
--TRANSACTION_STS Enrolled
--One character code, lookup list value
--C :Current
--D :Dropped
--H :History
--P :Pre-registered
--R :Reserved
--W :Wait listed
CASE
WHEN Enrolled = 'C' THEN 'Y'
ELSE 'N'
END AS "EnrolledDer", --Enrolled Derived Column
--DropFlag,
LAST_DTE_OF_ATTEND LastDateEnrolled, --Populate last date enrolled if enrolled flag above is N
CASE
WHEN EnrolledDer = 'N' then LAST_DTE_OF_ATTEND --'Invalid Column named EnrolledDer'
ELSE NULL
END AS LastDateEnrolledDer, --LastDateEnrolledDer Derived Column
Building,
Room,
ROW_NUMBER() OVER(PARTITION BY [Student ID],
[Unique Course Identifier]
ORDER BY [Start Time]) as rn
FROM cteAccScheduleFull
This related post has test data https://dba.stackexchange.com/questions/308550/convert-7-columns-in-two-rows-to-14-columns-in-one-row/308555#308555
I got this case statement to work with a nested case. I'm not sure what the best way to indent that is. I don't like repeating code. Would another solution be to use a cte or function?
--Populate last date enrolled if enrolled flag above is N
-- CASE
-- WHEN EnrolledDer = 'N' then LAST_DTE_OF_ATTEND
--ELSE NULL
-- END AS LastDateEnrolledDer, --LastDateEnrolledDer Derived Column
CASE
WHEN CASE
WHEN Enrolled = 'C' THEN 'Y'
ELSE 'N'
END
= 'N' then LAST_DTE_OF_ATTEND
ELSE NULL
END AS LastDateEnrolledDer, --LastDateEnrolledDer Derived Column
Aliasing an expression is done through cross apply. Change your FROM to:
FROM
cteAccScheduleFull
cross apply
(select CASE
WHEN Enrolled = 'C' THEN 'Y'
ELSE 'N'
END AS EnrolledDer --Enrolled Derived Column
) as q1
Then you will be able to use q1.EnrolledDer in your select any number of times. You can even chain cross apply blocks if you had more dependent expressions.

Using Case statement in Where clause in Oracle SQL

I have a select statement like below
select *
from employees
where emp_id <= v_emp_id;
I want this emp_id to be <= v_emp_id if country is not USA.
If country is USA, then I want emp_id to be = v_usa_emp_id.
Your question is a bit ambiguous. I have assumed that country is an attribute in the table employees of data type VARCHAR.
SELECT * FROM employees
WHERE
(emp_id = v_emp_id AND country = 'USA')
OR (emp_id <= v_emp_id AND country != 'USA')
You might want to take a look at WHERE, OR and AND.
Quoting the OR page linked above:
If you use multiple logical operators in a statement, Oracle evaluates the OR operators after the NOT and AND operators. However, you can change the order of evaluation by using parentheses.

Is it possible to bulk update specific values in postgresql efficiently?

I have created a pipeline which is required to update a high number of rows in postgres where each row should be updated differently.
After looking up I found that this could be done using postgres UPDATE.. FROM.. syntax (https://www.postgresql.org/docs/current/sql-update.html) and I came up with the following query that works perfectly fine:
update grades
set course_id = data_table.course_id,
student_id = data_table.student_id,
grade = data_table.grade
from
(select unnest(array[1,2]) as id, unnest(array['Math', 'Math']) as course_id, unnest(array[1000, 1001]) as student_id, unnest(array[95, 100]) as grade) as data_table
where grades.id = data_table.id;
There's also another way to do it with WITH syntax like this:
update grades
set course_id = data_table.course_id,
student_id = data_table.student_id,
grade = data_table.grade
from
(WITH vals (id, course_id, student_id, grade) as (VALUES (1, 'Math', 1000, 95), (2, 'Math', 1001, 100)) SELECT * from vals) as data_table
where grades.id = data_table.id;
My problem is that sometimes I want in some raws to update a field and sometime not. When I don't want to update I just want to keep the value that is currently in the table. In this case, I would want to potentially do something like:
update grades g
set course_id = data_table.course_id,
student_id = data_table.student_id,
grade = data_table.grade
from
(select unnest(array[1,2]) as id, unnest(array[g.course_id, 'Math2']) as course_id, unnest(array[1000, 1001]) as student_id, unnest(array[95, g.grade]) as grade) as data_table
where grades.id = data_table.id;
However this is not possible and I get back the error HINT: There is an entry for table "g", but it cannot be referenced from this part of the query.
Also postgresql documentation specifies about it in the From description:
Note that the target table must not appear in the from_list,
unless you intend a self-join (in which case it must appear with an alias in the from_list).
Does anyone know if there's a way to perform such bulk update ?
I've tried to use JOINs in inner query but with no luck..
Chose a value that cannot be a valid value, eg '-1' for course name and -1 for a grade, and use that for your generated values, then use a case in the insert to direct whether to use the current value or not:
update grades g
set course_id = case when data_table.course_id = '-1' then course_id else data_table.course_id end,
student_id = data_table.student_id,
grade = case when data_table.grade = -1 then g.grade else data_table.grade end
from (
select
unnest(array[1,2]) as id,
unnest(array['-1', 'Math2']) as course_id, -- use '-1' instead of g.course_id
unnest(array[1000, 1001]) as student_id,
unnest(array[95, -1]) as grade -- use -1 instead of g.grade
) as data_table
where grades.id = data_table.id
Pick whatever values you like for the impossible value.
If nulls were not allowed it would have been more straightforward and less code - use null for the impossible value and coalesce() in for the update value.

How to get a sum of all rows that meets condition in postgres

I am trying to return sums with their specific conditions.
SELECT
COUNT(*),
SUM("transactionTotal" WHERE "entryType"=sold) as soldtotal,
SUM(case when "entryType"=new then "transactionTotal" else 0 end) as newtotal
FROM "MoneyTransactions"
WHERE cast("createdAt" as date) BETWEEN '2020-10-08' AND '2020-10-09'
I am trying to sum up the rows with "entryType"=sold and "entryType"=new and return those values separately.
obviously both my logic are wrong.
can someone lend a hand.
You were on the right track to use conditional aggregation, but your syntax is slightly off. Try this version:
SELECT
COUNT(*) AS total_cnt,
SUM(transactionTotal) FILTER (WHERE entryType = 'sold') AS soldtotal,
SUM(transactionTotal) FILTER (WHERE entryType = 'new') AS newtotal
FROM MoneyTransactions
WHERE
createdAt::date BETWEEN '2020-10-08' AND '2020-10-09';
Note: Assuming your createdAt column already be date, then there is no point in casting it. If it is text, then yes you would need to convert it, but you might have to use TO_DATE depending on its format.

Case statement based on the result Postgresql

Hi so I have a question regarding case statements and why certain statements dont work.
(Case WHEN LENGTH(input)<=5 THEN text LIKE '%'
ELSE text = input)
When I did this, it didnt work and im still confused as to why.
However the solution to this problem was
(Case WHEN LENGTH(input)<=5 THEN text LIKE Concat('%',input,'%')
ELSE text = input END)
However My main question is below though I would like an answer to the above question and since they are identical I will leave it as one question.
I have a student who is still being reviewed for entering the school, however this school is german so i need to translate a few words for them since the system is in English
select s.fname, s.lastname,
(Case when s.status like 'APPROVED' then s.status = 'Genehmigt'
when s.status like 'PENDING' then s.status = 'Anstehend.'
end) as Status
from Student
My results are giving me False in the status field so obviously im doing something wrong...
And I know there are two types of case statement so am I using the recommended one?
The expression you have placed after then:
s.status = 'Genehmigt'
is not an assignment, it is a boolean expression, so it yields true or false.
s.status = is just redundant.
select
fname,
lastname,
case when status = 'APPROVED' then 'Genehmigt'
when status = 'PENDING' then 'Anstehend.'
end as status
from student
Note that like with a string without wildcards on the right side should be a simple comparison.