Replace empty date values with a matching value from the same column? - sql

I have a small query that looks like this:
SELECT
CS.ID,
CS.Import_Date,
CS.Secondary_Date
FROM
Center_Summary CS
ORDER BY CS.Import_Date
Which returns values like this:
And I want to replace these "empty" values which are pulling as 01/01/1900 with the value of 05/01/2019. In this case, it's because the ID and Import_Date match, so the Secondary_Date should match as well. I've thought to use REPLACE() (REPLACE(CS.Secondary_Date, '01/01/1900', ???), but I'm not sure how to write logic to pull in a matching value from the column Secondary_Date based on ID and Import_Date - what function should I be looking to use here?
How it's currently pulling (the dates in red I want to replace):
What my expected result is:

Why not just use a UPDATE with a WHERE?
UPDATE dbo.YourTable
SET SecondaryDate = ImportDate
WHERE SecondaryDate = '19000101';

"Empty" values are best represented by NULL. I would recommend converting them to NULL:
nullif(secondary_date, '1900-01-01')
If you really want another value, then you can use coalesce() or a case expression:
coalesce(nullif(secondary_date, '1900-01-01'), '2019-05-01')
However, I'm not generally a fan of such magic values in the code.

Related

Adding column to table based on whether another column = a specific string

I want to add a column called "Sweep" that contains bools based on whether the "Result" was a sweep or not. So I want the value in the "Sweep" column to be True if the "Result" is '4-0' or '0-4' and False if it isn't.
This is a part of the table:
I tried this:
ALTER TABLE "NBA_finals_1950-2018"
ADD "Sweep" BOOL;
UPDATE "NBA_finals_1950-2018"
SET "Sweep" = ("Result" = '4-0' OR "Result" = '0-4');
But for some reason, when I run this code...:
SELECT *
FROM "NBA_finals_1950-2018"
ORDER BY "Year";
...only one of the rows (last row) has the value True even though there are other rows where the result is a sweep ('4-0' or '0-4') as shown in the picture below.
I don't know why this is happening but I guess there is something wrong with the UPDATE...SET code. Please help.
Thanks in advance.
NOTE: I am using PostgreSQL 13
This would occur if the strings are not really what they look like -- this is often due to spaces at the beginning or end. Or perhaps to hyphens being different, or other look-alike characters.
You just need to find the right pattern. So so with a select. This returns no values:
select *
from "NBA_finals_1950-2018"
where "Result" in ('4-0', '0-4');
You can try:
where "Result" like '%0-4%' or
"Result" like '%4-0%'
But, this should do what you want:
where "Result" like '%4%' and
"Result" like '%0%'
because the numbers are all single digits.
You can incorporate this into the update statement.
Note: double quotes are a bad idea. I would recommend creating tables and columns without escaping the names.

Select sub queries within a select

insert into time_test(Difference) values
(select ((select actual from time_test where id = :p13_id) -
(select
(monday+tuesday+wednesday+thursday+friday) from time_test where id=
:p13_id
)) from time_test where id= :p13_id)
Difference is a column in time_test which is null, and :p13_id is a page item for Oracle Apex.
I know I need to wrap it in nvl or some function like that but I don't know how.
It looks like you're actually trying to do an update, not an insert:
update time_test
set difference = actual - (monday+tuesday+wednesday+thursday+friday)
where id = :p13_id
If any of the 'day' columns might be null then you can use nvl() or coalesce() to default them to zero so they don't break the calculation:
update time_test
set difference = actual - coalesce(monday, 0) - coalesce(tuesday, 0)
- coalesce(wednesday, 0) - coalesce(thursday, 0) - coalesce(friday, 0)
where id = :p13_id
You could also do coalesce(actual, 0) but it might make more sense to leave the difference null if that is not set. It depends what you want to see in that case.
In this case the nvl() and coalesce() functions are equivalent. If the first argument - e.g. monday - is null then the second argument is substituted. So nvl(monday, 0) will give you the actual value of monday if it is not null, but will give you zero if it is null. You will get the same effect from coalesce(), but that allows a list of multiple expressions to be evaluated and will return the first non-null value from the list.
Another approach to this is to make difference a virtual column that is calculated on the fly, or calculate it in a view over the table; either would remove the duplicate data storage and the need to maintain the value yourself. And if you did definitely want a physical column you could set it from a trigger so automate the maintenance in case any of the other columns are updated outside your Apex application. But a virtual column is probably simpler and neater.

SQL Select to keep out fields that are NULL

I am trying to connect a Filemaker DB to Firebird SQL DB in both ways import to FM and export back to Firebird DB.
So far it works using the MBS Plug-in but FM 13 Pro canot handle NULL.
That means that for example Timestamp fields that are empty (NULL) produce a "0" value.
Thats means in Time something like 01.01.1889 00:00:00.
So my idea was to simply ignore fields containing NULL.
But here my poor knowlege stops.
First I thought I can do this with WHERE, but this is ignoring whole records sets:
SELECT * FROM TABLE WHERE FIELD IS NOT NULL
Also I tried to filter it later on like this:
If (IsEmpty (MBS("SQL.GetFieldAsDateTime"; $command; "FIELD") ) = 0 ; MBS("SQL.GetFieldAsDateTime"; $command; "FIELD"))
With no result either.
This is a direct answer to halfbit's suggestion, which is correct but not for this SQL dialect. In a query to provide a replacement value when a field is NULL you need to use COALESCE(x,y). Where if X is null, Y will be used, and if Y is null then the field is NULL. Thats why it is common for me to use it like COALESCE(table.field,'') such that a constant is always outputted if table.field happens to be NULL.
select COALESCE(null,'Hello') as stackoverflow from rdb$database
You can use COALESCE() for more than two arguments, I just used two for conciseness.
I dont know the special SQL dialect, but
SELECT field1, field2, value(field, 0), ...FROM TABLE
should help you:
value gives the first argument, ie, your field if it is NOT NULL or the second argument if it is.

SQL and iReport - Aggregate functions in the Where clause and Parameters

Well basically I would like to be able to use a parameter on iReport with an aggregate function.
If you type "yes" it will show you the values greater than 0, if you type "no" it will show the values that are less than 0. However, the aggregate function first adds up all the values related to an id and then it subtracts the result from another value, the result of that is the one I want to show.
How would I be able to do this? I'm clueless as I don't know how to use it with HAVING.
I don't understand what 'it' refers to in "I don't know how to use it with HAVING." The question will be much clearer with some SQL. But I guess you're looking for this:
SELECT id, sum(values) as the_agg
FROM table1
GROUP BY id
HAVING sum(values) $P!{BiggerOrSmaller} 0
The default value for the parameter BiggerOrSmaller should be like this:
$P{MyParam}.equals("yes") ? ">" : "<"
This assumes you have a parmeter called MyParam which can take the value "yes". Based on that value it sets the parameter BiggerOrSmaller appropriately.

Problem with MySQL Select query with "IN" condition

I found a weird problem with MySQL select statement having "IN" in where clause:
I am trying this query:
SELECT ads.*
FROM advertisement_urls ads
WHERE ad_pool_id = 5
AND status = 1
AND ads.id = 23
AND 3 NOT IN (hide_from_publishers)
ORDER BY rank desc
In above SQL hide_from_publishers is a column of advertisement_urls table, with values as comma separated integers, e.g. 4,2 or 2,7,3 etc.
As a result, if hide_from_publishers contains same above two values, it should return only record for "4,2" but it returns both records
Now, if I change the value of hide_for_columns for second set to 3,2,7 and run the query again, it will return single record which is correct output.
Instead of hide_from_publishers if I use direct values there, i.e. (2,7,3) it does recognize and returns single record.
Any thoughts about this strange problem or am I doing something wrong?
There is a difference between the tuple (1, 2, 3) and the string "1, 2, 3". The former is three values, the latter is a single string value that just happens to look like three values to human eyes. As far as the DBMS is concerned, it's still a single value.
If you want more than one value associated with a record, you shouldn't be storing it as a comma-separated value within a single field, you should store it in another table and join it. That way the data remains structured and you can use it as part of a query.
You need to treat the comma-delimited hide_from_publishers column as a string. You can use the LOCATE function to determine if your value exists in the string.
Note that I've added leading and trailing commas to both strings so that a search for "3" doesn't accidentally match "13".
select ads.*
from advertisement_urls ads
where ad_pool_id = 5
and status = 1
and ads.id = 23
and locate(',3,', ','+hide_from_publishers+',') = 0
order by rank desc
You need to split the string of values into separate values. See this SO question...
Can Mysql Split a column?
As well as the supplied example...
http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/
Here is another SO question:
MySQL query finding values in a comma separated string
And the suggested solution:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set