Using A case in a select to detect a null date - tsql

I'm trying to return all records that have a Fee against them that need paying (pd.[Plan Fee] not null), But do not have a date of invoice being raised against them (pd.[Raise Plan Fee] NULL).
I'm relatively new to using cases, so not sure this is the correct way to execute what i'm trying to return, any help or advice would be greatly appreciated.
SELECT * FROM
vw_ProjectsDetailed AS pd WHERE
CASE pd.[Plan Fee] WHEN NOT NULL THEN pd.[Raise Plan Fee] NULL

Related

Cannot use Named Parameters with SSRS and PostgreSQL

I'm trying to add named parameters to a dataset query in a SSRS report (I'm using Report Builder), but I have had no luck discovering the correct syntax. I have tried #parameter, $1, $parameter and others, all without success. I suspect the syntax is just different for PostgreSQL versus normal SQL.
The only success I have had with passing parameters was based on this answer.
It involves using ? for every single parameter.
My query might look something like this:
SELECT address, code, remarks FROM table_1 WHERE date BETWEEN ? AND ? AND apt_num IS NULL AND ADDRESS = ?
This does work, but in the case of a query where I pass the same parameter to more than one part of the SELECT statement, I have to add the same parameter to the list multiple times as shown here. They are passed in this order, so adding a new parameter to an existing query results in having to reshuffle, and sometimes completely rebuild, the query parameters tab.
What are the proper syntax and naming requirements for adding named Parameters when using a PostgreSQL data source in SSRS?
From my comment, this is what it would look like with a regular join:
with inparms as (
select ? as from_date, ? as to_date, ? as address
)
select t.address, t.code, t.remarks
from inparms i
join table_1 t
on t.date between i.from_date and i.to_date
and t.apt_num is null
and t.address = i.address;
I said cross join in my comment because it is sometimes quicker when retrofitting somebody else's SQL instead of trying to untangle things (thinking of a friend who uses right join sometimes just to ruin my day).

Can hibernate embed values of a query before sending to postgres rather than sending a query with where c.col=?

If I have a JQL query in hibernate select c from Customer c where c.col=:col
Is there a way to get hibernate to send the query prepopulated to JDBC preparedstatement?
ie. Can I get hibernate to send this
select c.col, c.name, c.id, etc from Customer c where c.col=value (or NULL)
instead of
select c.col, c.name, c.id, etc from Customer c where c.col=?
Ideally hibernate would also tweak the Strings correctly so SQL injection is prevented as well.
postgres has a setting so null = null and people have been making mistakes thinking null = null without that setting. I actually think null = nulll should work and makes more sense myself. However, in SQL, "WHERE c.col = :col" are not equal if both sides are null. We realize this is a deviation from SQL spec but it's better to not be introducing all these bugs going forward as we hire more junior engineers. ie. better to have a stable product and business then follow some standard in some cases so we can move fast without worry of those bugs.
There are a ton of questions on SO also about null != null in SQL. I am also not very sure why "c.col is null" gets to be correct while "c.col = null" is wrong and returns 0 rows always. I think some people desire to never have null and want c.col = null to 'fail' but of course, it really fails silently which is more annoying since we don't catch the bug. If it failed hard core, at least our developers would then stop and ask, what in the world is going on.

Postgres COALESCE inside nullif for 2 different fields

I am new to SQL and POSTGRES and had a quick question. Right now I have 2 different tables one with car info and one with partial car info and I would like to sort on car.vin OR partial_car.vin depending if either exists and sending all nulls/empty strings to the end of the sort. Currently my ORDER BY statement looks like:
ORDER BY nullif(coalesce(car.vin, partial_car.partial_vin), '') asc nulls last limit 50 offset 0
My expectation for this is that coalesce will take the first non null value and use that for sorting or it will return null and send that to the end. My results so far I haven't been able to make sense of. There are null values being placed in between actual values etc.. If I make this change coalesce(car.vin, '') again I see it work properly. Anyone have an ideas as to why this is the behavior? Let me know if you need something more from me.
It was human error on my end. The object being sent to client was not being populated properly with partial data. So sorting was correct but was seeing blanks due to those values not being present.

Converting complex query with inner join to tableau

I have a query like this, which we use to generate data for our custom dashboard (A Rails app) -
SELECT AVG(wait_time) FROM (
SELECT TIMESTAMPDIFF(MINUTE,a.finished_time,b.start_time) wait_time
FROM (
SELECT max(start_time + INTERVAL avg_time_spent SECOND) finished_time, branch
FROM mytable
WHERE name IN ('test_name')
AND status = 'SUCCESS'
GROUP by branch) a
INNER JOIN
(
SELECT MIN(start_time) start_time, branch
FROM mytable
WHERE name IN ('test_name_specific')
GROUP by branch) b
ON a.branch = b.branch
HAVING avg_time_spent between 0 and 1000)t
GROUP BY week
Now I am trying to port this to tableau, and I am not being able to find a way to represent this data in tableau. I am stuck at how to represent the inner group by in a calculated field. I can also try to just use a custom sql data source, but I am already using another data source.
columns in mytable -
start_time
avg_time_spent
name
branch
status
I think this could be achieved new Level Of Details formulas, but unfortunately I am stuck at version 8.3
Save custom SQL for rare cases. This doesn't look like a rare case. Let Tableau generate the SQL for you.
If you simply connect to your table, then you can usually write calculated fields to get the information you want. I'm not exactly sure why you have test_name in one part of your query but test_name_specific in another, so ignoring that, here is a simplified example to a similar query.
If you define a calculated field called worst_case_test_time
datediff(min(start_time), dateadd('second', max(start_time), avg_time_spent)), which seems close to what your original query says.
It would help if you explained what exactly you are trying to compute. It appears to be some sort of worst case bound for avg test time. There may be an even simpler formula, but its hard to know without a little context.
You could filter on status = "Success" and avg_time_spent < 1000, and place branch and WEEK(start_time) on say the row and column shelves.
P.S. Your query seems a little off. Don't you need an aggregation function like MAX or AVG after the HAVING keyword?

Postgresql CASE statement - can I use the return value of the CASE within my SELECT?

I have a products database with multiple tables to store pricing (because of default pricing and optional override pricing per product colour), and I have CASE statements in my query to get the
* Original price of the product
* Sale price of the product, if it is on sale
I also need to calculate the DISCOUNT of the product if it is on sale. Before I try this, please see the breakdown of my existing SQL which works.
SELECT p.productid, p.stylename,
CASE WHEN (ppo.original_price IS NOT NULL) THEN ppo.original_price ELSE pp.original_price END AS final_original_price,
CASE WHEN (ppo.original_price IS NOT NULL) THEN ppo.sale_price ELSE pp.sale_price END AS final_sale_price
FROM product p, ... etc.
The above code works (I have simplified it), and basically, the original price of the product is stored in the column alias "final_original_price", and the sale price (which might be NULL) is returned as "final_sale_price".
I now want to add an additional line to the SELECT to get the discount. I can't use the existing fields in the actual table because I want those return values of "final_original_price" and "final_sale_price" to do the calculations.
e.g.
SELECT p.productid, p.stylename,
CASE WHEN (ppo.original_price IS NOT NULL) THEN ppo.original_price ELSE pp.original_price END AS final_original_price,
CASE WHEN (ppo.original_price IS NOT NULL) THEN ppo.sale_price ELSE pp.sale_price END AS final_sale_price,
((final_original_price - final_sale_price) / final_original_price * 100) AS final_discount_percentage
FROM product p, ... etc.
The above does not work, as Postgresql returns "ERROR: column "final_original_price" does not exist at character....."
So, clearly I can't use the return value of the CASE. My questions on what solution to use:
1) Can I indeed use the return value of the case like I want to, above?
OR
2) Do I need to again plug in the case statement to my calculation? That means I need to repeat the CASE code and the query will look quite lengthy. If I have to, I'd do this, but I'm just wondering if there's a better way.
OR
3) I could also store an additional field in the database to store the discount. This data would be redundant because my CMS would need to ensure that the field is updated whenever the price is updated. However it would save heavy calculations (if the above is considered heavy) on the front end which runs much more often than the backend CMS.
The above solutions are probably the easiest, but I am also wondering, if I had time to do this, are there any other solutions here that would be worth considering? For example would this be a good scenarios to write a "view"? Personally I have never set up a view and as far as I understand, the database-selection work is still happening in the background, but, if set up, would make the end query above simpler to understand from a developer's point of view.
Many thanks!
use
SELECT
productid,
stylename,
final_original_price,
final_sale_price,
((final_original_price - final_sale_price) / final_original_price * 100) AS final_discount_percentage
FROM
(
SELECT p.productid, p.stylename,
CASE WHEN (ppo.original_price IS NOT NULL) THEN ppo.original_price ELSE pp.original_price END AS final_original_price,
CASE WHEN (ppo.original_price IS NOT NULL) THEN ppo.sale_price ELSE pp.sale_price END AS final_sale_price
FROM product p, ... etc.
)
The above does exactly what you asked for... if for some reason you don't want to use it then plugin the CASE statements into the calculation (option 2 from your question).