sql query to get the column value again in case statement - sql

select *,
case when number = '12' and status = 'y' then cost
end as [price]
from tblx
i got the results from the above query, i want to use the value of price column, again in case statement of the same query as like below
select *,
case when number = '12' and status = 'y' then cost-500
end as [price],
case when price = 24 then trasdate end as [trasdate]
from tblx
If my question is not clear, please suggest me
I am working in a stored procedure with more than two joins connecting 8 tables, i just want to get the column value again to use it on case statement on the same query, I shortened the question as the query is bigger.
Thanks

In the same query you need to just duplicate the same case statement where you've attempted to reference it. Btw you should probably add an else 0 to it because currently it'll return null if your conditions don't evaluate to true which could affect its usage in the other case statement.
There are other options if you don't want to duplicate the case statement e.g.:
use the price statement in a sub query and reference it by name in an outer query
use a temp table with price added as a calculated column
as above but use a table variable
Just repeating the statement is obviously simplest and may well perform best too, downside is duplication. In terms of performance, test for your likely use case.

select *,
case when number = '12' and status = 'y' then cost end price,
case when number = '12' and status = 'y'
and cost = 24 then trasdate end [trasdate]
from tblx

Related

SQL use intermediate results

I have a column with numbers (float) that I would like to categorize and store a category as integer and as label (string). For now assume that the category is simply defined by the FLOOR(x).
This works:
SELECT salary,
FLOOR(salary) AS category_integer,
CASE WHEN FLOOR(salary) = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM test01
but I was wondering if I could use the intermediate variable 'category_integer' defined in the beginning of my query in a later part, something like this:
SELECT salary,
FLOOR(salary) AS category_integer,
CASE WHEN category_integer = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM test01
but this is apparently not how SQL works. I've looked into Common table Expressions but got lost there. Is there a way to reuse intermediate variables in an SQL expression?
SQL Fiddle
I must have missed this but I couldn't find related questions so far.
You may resort to common table expressions - basically a query that produces a labelled result set you can refer to in subsequent queries.
Adapted to your example:
with cte as (
select salary
, floor(salary) as category_integer
from test01
)
SELECT salary
, category_integer
, CASE WHEN category_integer = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM cte
;
Consult the reference for more details: CTE / WITH in pgSQL 9.6.
See it at work in SQL fiddle.
There are pre- and post-selection operations. For example order by and group by are post-selection instructions, distinct for example filters out duplicate results during the selection proces itself and as such duplicate results do not even enter the result set to be ordered or grouped.
When you use AS, you are telling PostgreSQL to take the result and put it in a column named category_integer in the output. You are not actually making a variable here that's available during query execution, as the result is only available after the query executes. As such, you can only do this with subselects where you have the result available as a virtual table in itself, where category_integer is a column in a table rather than a variable.
SELECT category_integer,
CASE WHEN category_integer = 0
THEN 'foo'
ELSE 'bar'
END AS category_label
FROM (SELECT FLOOR(0) AS category_integer FROM test01) AS test02
https://www.postgresql.org/docs/current/static/queries-select-lists.html
https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-TABLE-ALIASES

SQL select query to return one row for data with or without fragile

I have a shipping table with some shipments have fragile material and others don't. I would like to return only one row for each shipment either Fragile or not. I'm using a case statement and right now it breaks it into two rows for the shipments that have both Fragile and non-Fragile materials. Can you please suggest any method to do this?
,Case when mat.Frag = 'F' then 'YES' else 'N/A' end as Fragile
I'm already using groups an this column is also in group by clause
I think I got it
I can use:
Case When exists( Select mat.Frag from Materials
where mat.Frag = 'F')
then 'F' else '' End as Fragile

Oracle 11g, how to speed up an 'in' query

I was trying to create a view and needed to create a column that shows if the 'somenumber' column exists on other table or not. The code below worked but very slowly. Is it possible to declare a table as (select someNumber from veryYugeTable) and check on that one instead of sending this query for every single record or using some other way to speed up the view?
case
when someOtherTable.someNumber in(select someNumber from veryYugeTable) then 'exists'
else 'doesn't exist'
end as "someColumn"
The query looks fine. You should have an index on veryYugeTable.someNumber.
Sometimes the optimizer handles correlated subqueries better than non-correlated ones, so you can try:
case
when exists
(
select *
from veryYugeTable
where veryYugeTable.someNumber = someOtherTable.someNumber
) then 'exists'
else 'doesn''t exist'
end as "someColumn"
(Well, as this query does exactly the same as yours, the optimizer should get to the same execution plan, but this is not always the case.)
But as mentioned: Make sure first to have that index.
You might find you get some benefit with scalar subquery caching if you do something like:
coalesce((select 'exists'
from veryyugetable vyt
where vyt.somenumber = someOtherTable.someNumber
and rownum = 1),
'doesn''t exist') somecolumn
N.B. the and rownum = 1 is not necessary if vyt.somenumber is a unique column. Also, I nth the suggest to index the vyt.somenumber column.
use left join instead of putting the in clause in select:
left join veryYugeTable on someNumber = someOtherTable.someNumber
adjust your case when statement as follow:
case
when veryYugeTable.OtherColumn is null then 'doesn''t exist'
else 'exist'
end as "someColumn"

teradata case when issue

I have the following queries which are supposed to give the same result, but drastically different
1.
select count(*)
from qigq_sess_parse_2
where str_vendor = 'natural search' and str_category is null and destntn_url = 'http://XXXX.com';
create table qigq_test1 as
(
select case
when (str_vendor = 'natural search' and str_category is null and destntn_url = 'http://XXXX.com' ) then 1
else 0
end as m
from qigq_sess_parse_2
) with data;
select count(*) from qigq_test1 where m = 1;
the first block gives a total number of count 132868, while the second one only gives 1.
What are the subtle parts in the query that causes this difference?
Thanks
When you create a table in Teradata, you can specify it to be SET or MULTISET. If you don't specify, it defaults to SET. A set table cannot contain duplicates. So at most, your new table will contain two rows, a 0 and a 1, since that's all that can come from your case statement.
EDIT:
After a bit more digging, the defaults aren't quite that simple. But in any case, I suspect that if you add the MULTISET option to your create statement, you'll see the behavior your expect.
My guess would be that your Create Table statement is only pulling in one row of data that fits the parameters for the following Count statement. Try this instead:
CREATE TABLE qigq_test1 (m integer);
INSERT INTO qigq_test1
SELECT
CASE
WHEN (str_vendor = 'natural search' and str_category IS NULL AND destntn_url = 'http://XXXX.com' ) THEN 1
ELSE 0
END AS m
FROM qigq_sess_parse_2;
SELECT COUNT(*) FROM qigq_test1 WHERE m = 1;
This should pull ALL ROWS of data from qigq_sess_parse_2 into qigq_test1 as either a 0 or 1.

T-SQL 2005: Counting All Rows and Rows Meeting Criteria

Here's the scenario:
I have a table with 3 columns: 'KeyColumn', 'SubKeyColumn' and 'BooleanColumn', where the first two are the primary keys of the table.
For my query, I'd like to count the number of rows there are for any given value in 'KeyColumn', and I'd also like to know which ones have a value of true for 'BooleanColumn'. My initial thought was to create a query like this:
SELECT
COUNT(*)
,COUNT(CASE WHEN BooleanColumn = 1 THEN 1 ELSE 0 END)
FROM
MyTable
GROUP BY
KeyColumn
However, the 2nd part does not work (I'm not entirely sure why I thought it would to begin with). Is it possible to do something like this in one query? Or am I going to need to do multiple queries to make this happen?
Change COUNT to SUM in the 2nd part. ;)
... CASE WHEN BooleanColumn = 1 THEN 1 ELSE NULL END ...
COUNT counts the NON-NULL rows.
You could also do SUM(CAST(BooleanColumn AS TINYINT))